Merge "Handle night display state when timezone changes" into oc-mr1-dev
diff --git a/Android.mk b/Android.mk
index 19bbc5f..77a4d83 100644
--- a/Android.mk
+++ b/Android.mk
@@ -502,9 +502,9 @@
 	telecomm/java/com/android/internal/telecom/IInCallService.aidl \
 	telecomm/java/com/android/internal/telecom/ITelecomService.aidl \
 	telecomm/java/com/android/internal/telecom/RemoteServiceCallback.aidl \
-        telephony/java/android/telephony/mbms/IMbmsDownloadManagerCallback.aidl \
-	telephony/java/android/telephony/mbms/IMbmsStreamingManagerCallback.aidl \
-	telephony/java/android/telephony/mbms/IDownloadProgressListener.aidl \
+	telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl \
+	telephony/java/android/telephony/mbms/IMbmsStreamingSessionCallback.aidl \
+	telephony/java/android/telephony/mbms/IDownloadStateCallback.aidl \
         telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl \
 	telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl \
 	telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl \
diff --git a/api/test-current.txt b/api/test-current.txt
index 62f8885..9487740 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -12093,6 +12093,18 @@
     ctor public SQLiteFullException(java.lang.String);
   }
 
+  public final class SQLiteGlobal {
+    method public static java.lang.String getDefaultJournalMode();
+    method public static int getDefaultPageSize();
+    method public static java.lang.String getDefaultSyncMode();
+    method public static int getIdleConnectionTimeout();
+    method public static int getJournalSizeLimit();
+    method public static int getWALAutoCheckpoint();
+    method public static int getWALConnectionPoolSize();
+    method public static java.lang.String getWALSyncMode();
+    method public static int releaseMemory();
+  }
+
   public class SQLiteMisuseException extends android.database.sqlite.SQLiteException {
     ctor public SQLiteMisuseException();
     ctor public SQLiteMisuseException(java.lang.String);
diff --git a/cmds/bu/src/com/android/commands/bu/Backup.java b/cmds/bu/src/com/android/commands/bu/Backup.java
index 345895b..834658d 100644
--- a/cmds/bu/src/com/android/commands/bu/Backup.java
+++ b/cmds/bu/src/com/android/commands/bu/Backup.java
@@ -136,7 +136,9 @@
             if (fd != null) {
                 try {
                     fd.close();
-                } catch (IOException e) {}
+                } catch (IOException e) {
+                    Log.e(TAG, "IO error closing output for backup: " + e.getMessage());
+                }
             }
         }
     }
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 47f81b8..ff61d18 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -1159,6 +1159,7 @@
 android.icu.impl.ICUService$CacheEntry
 android.icu.impl.ICUService$Factory
 android.icu.impl.ICUService$Key
+android.icu.impl.IDNA2003
 android.icu.impl.LocaleIDParser
 android.icu.impl.LocaleIDs
 android.icu.impl.Norm2AllModes
@@ -1254,6 +1255,7 @@
 android.icu.impl.locale.LocaleObjectCache
 android.icu.impl.locale.LocaleObjectCache$CacheEntry
 android.icu.impl.locale.LocaleSyntaxException
+android.icu.impl.number.Parse
 android.icu.lang.UCharacter
 android.icu.lang.UCharacterEnums$ECharacterCategory
 android.icu.lang.UCharacterEnums$ECharacterDirection
@@ -1468,6 +1470,7 @@
 android.media.IRingtonePlayer$Stub
 android.media.IRingtonePlayer$Stub$Proxy
 android.media.Image
+android.media.ImageReader
 android.media.JetPlayer
 android.media.MediaCodec$BufferInfo
 android.media.MediaCodec$BufferMap
@@ -1478,9 +1481,11 @@
 android.media.MediaCodecInfo$CodecProfileLevel
 android.media.MediaCodecInfo$Feature
 android.media.MediaCodecInfo$VideoCapabilities
+android.media.MediaCodecList
 android.media.MediaFormat
 android.media.MediaMetadata$1
 android.media.MediaMetadata$Builder
+android.media.MediaPlayer
 android.media.MediaPlayer$1
 android.media.MediaPlayer$2
 android.media.MediaPlayer$EventHandler
@@ -1511,6 +1516,7 @@
 android.media.PlayerBase$PlayerIdCard$1
 android.media.RemoteDisplay
 android.media.Ringtone$MyOnCompletionListener
+android.media.SoundPool
 android.media.SubtitleController$Listener
 android.media.ToneGenerator
 android.media.Utils
@@ -2050,6 +2056,7 @@
 android.text.GetChars
 android.text.GraphicsOperations
 android.text.Html
+android.text.Html$HtmlParser
 android.text.HtmlToSpannedConverter$Href
 android.text.Hyphenator
 android.text.Hyphenator$HyphenationData
@@ -2099,6 +2106,7 @@
 android.text.TextUtils$StringSplitter
 android.text.TextUtils$TruncateAt
 android.text.TextWatcher
+android.text.format.Formatter
 android.text.format.Time$TimeCalculator
 android.text.method.AllCapsTransformationMethod
 android.text.method.ArrowKeyMovementMethod
@@ -4500,6 +4508,7 @@
 org.ccil.cowan.tagsoup.AutoDetector
 org.ccil.cowan.tagsoup.Element
 org.ccil.cowan.tagsoup.ElementType
+org.ccil.cowan.tagsoup.HTMLScanner
 org.ccil.cowan.tagsoup.HTMLSchema
 org.ccil.cowan.tagsoup.Parser$1
 org.ccil.cowan.tagsoup.ScanHandler
diff --git a/config/preloaded-classes-extra b/config/preloaded-classes-extra
index 1934cbc..959fff5 100644
--- a/config/preloaded-classes-extra
+++ b/config/preloaded-classes-extra
@@ -1 +1,13 @@
 android.icu.impl.coll.CollationRoot
+android.icu.impl.IDNA2003
+android.icu.impl.number.Parse
+android.icu.util.TimeZone
+android.media.ImageReader
+android.media.MediaCodecList
+android.media.MediaPlayer
+android.media.SoundPool
+android.text.format.Formatter
+android.text.Html$HtmlParser
+com.android.org.conscrypt.TrustedCertificateStore
+org.ccil.cowan.tagsoup.HTMLScanner
+sun.security.jca.Providers
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index cec5db9..a558d68 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -26,7 +26,6 @@
 import android.content.Intent;
 import android.content.pm.ParceledListSlice;
 import android.graphics.Region;
-import android.hardware.fingerprint.FingerprintManager;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -52,8 +51,6 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.List;
 
-import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
-
 /**
  * Accessibility services should only be used to assist users with disabilities in using
  * Android devices and apps. They run in the background and receive callbacks by the system
@@ -394,7 +391,7 @@
     public static final int SHOW_MODE_AUTO = 0;
     public static final int SHOW_MODE_HIDDEN = 1;
 
-    private int mConnectionId;
+    private int mConnectionId = AccessibilityInteractionClient.NO_ID;
 
     private AccessibilityServiceInfo mInfo;
 
@@ -1612,7 +1609,7 @@
 
         private final Callbacks mCallback;
 
-        private int mConnectionId;
+        private int mConnectionId = AccessibilityInteractionClient.NO_ID;
 
         public IAccessibilityServiceClientWrapper(Context context, Looper looper,
                 Callbacks callback) {
@@ -1707,7 +1704,8 @@
                     if (event != null) {
                         // Send the event to AccessibilityCache via AccessibilityInteractionClient
                         AccessibilityInteractionClient.getInstance().onAccessibilityEvent(event);
-                        if (serviceWantsEvent) {
+                        if (serviceWantsEvent
+                                && (mConnectionId != AccessibilityInteractionClient.NO_ID)) {
                             // Send the event to AccessibilityService
                             mCallback.onAccessibilityEvent(event);
                         }
@@ -1721,7 +1719,9 @@
                 } return;
 
                 case DO_ON_INTERRUPT: {
-                    mCallback.onInterrupt();
+                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                        mCallback.onInterrupt();
+                    }
                 } return;
 
                 case DO_INIT: {
@@ -1746,8 +1746,10 @@
                 } return;
 
                 case DO_ON_GESTURE: {
-                    final int gestureId = message.arg1;
-                    mCallback.onGesture(gestureId);
+                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                        final int gestureId = message.arg1;
+                        mCallback.onGesture(gestureId);
+                    }
                 } return;
 
                 case DO_CLEAR_ACCESSIBILITY_CACHE: {
@@ -1779,37 +1781,51 @@
                 } return;
 
                 case DO_ON_MAGNIFICATION_CHANGED: {
-                    final SomeArgs args = (SomeArgs) message.obj;
-                    final Region region = (Region) args.arg1;
-                    final float scale = (float) args.arg2;
-                    final float centerX = (float) args.arg3;
-                    final float centerY = (float) args.arg4;
-                    mCallback.onMagnificationChanged(region, scale, centerX, centerY);
+                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                        final SomeArgs args = (SomeArgs) message.obj;
+                        final Region region = (Region) args.arg1;
+                        final float scale = (float) args.arg2;
+                        final float centerX = (float) args.arg3;
+                        final float centerY = (float) args.arg4;
+                        mCallback.onMagnificationChanged(region, scale, centerX, centerY);
+                    }
                 } return;
 
                 case DO_ON_SOFT_KEYBOARD_SHOW_MODE_CHANGED: {
-                    final int showMode = (int) message.arg1;
-                    mCallback.onSoftKeyboardShowModeChanged(showMode);
+                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                        final int showMode = (int) message.arg1;
+                        mCallback.onSoftKeyboardShowModeChanged(showMode);
+                    }
                 } return;
 
                 case DO_GESTURE_COMPLETE: {
-                    final boolean successfully = message.arg2 == 1;
-                    mCallback.onPerformGestureResult(message.arg1, successfully);
+                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                        final boolean successfully = message.arg2 == 1;
+                        mCallback.onPerformGestureResult(message.arg1, successfully);
+                    }
                 } return;
                 case DO_ON_FINGERPRINT_ACTIVE_CHANGED: {
-                    mCallback.onFingerprintCapturingGesturesChanged(message.arg1 == 1);
+                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                        mCallback.onFingerprintCapturingGesturesChanged(message.arg1 == 1);
+                    }
                 } return;
                 case DO_ON_FINGERPRINT_GESTURE: {
-                    mCallback.onFingerprintGesture(message.arg1);
+                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                        mCallback.onFingerprintGesture(message.arg1);
+                    }
                 } return;
 
                 case (DO_ACCESSIBILITY_BUTTON_CLICKED): {
-                    mCallback.onAccessibilityButtonClicked();
+                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                        mCallback.onAccessibilityButtonClicked();
+                    }
                 } return;
 
                 case (DO_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED): {
-                    final boolean available = (message.arg1 != 0);
-                    mCallback.onAccessibilityButtonAvailabilityChanged(available);
+                    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
+                        final boolean available = (message.arg1 != 0);
+                        mCallback.onAccessibilityButtonAvailabilityChanged(available);
+                    }
                 } return;
 
                 default :
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index 7d4d70d..9b2bfc5 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -1006,9 +1006,12 @@
         final int numElements = mTransitioningViews == null ? 0 : mTransitioningViews.size();
         for (int i = 0; i < numElements; i++) {
             final View view = mTransitioningViews.get(i);
-            view.setTransitionVisibility(visiblity);
             if (invalidate) {
-                view.invalidate();
+                // Allow the view to be invalidated by the visibility change
+                view.setVisibility(visiblity);
+            } else {
+                // Don't invalidate the view with the visibility change
+                view.setTransitionVisibility(visiblity);
             }
         }
     }
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index ba5ea21..0d5cd02 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1380,8 +1380,13 @@
                                     @Override
                                     public void onAnimationEnd(Animator anim) {
                                         container.endViewTransition(view);
-                                        if (fragment.getAnimatingAway() != null) {
-                                            fragment.setAnimatingAway(null);
+                                        Animator animator = f.getAnimatingAway();
+                                        f.setAnimatingAway(null);
+                                        // If the animation finished immediately, the fragment's
+                                        // view will still be there. If so, we can just pretend
+                                        // there was no animation and skip the moveToState()
+                                        if (container.indexOfChild(view) == -1
+                                                && animator != null) {
                                             moveToState(fragment, fragment.getStateAfterAnimating(),
                                                     0, 0, false);
                                         }
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 897e42b..1811748 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -308,7 +308,15 @@
     boolean shouldUpRecreateTask(in IBinder token, in String destAffinity);
     boolean navigateUpTo(in IBinder token, in Intent target, int resultCode,
             in Intent resultData);
-    void setLockScreenShown(boolean showing);
+    /**
+     * Informs ActivityManagerService that the keyguard is showing.
+     *
+     * @param showing True if the keyguard is showing, false otherwise.
+     * @param secondaryDisplayShowing The displayId of the secondary display on which the keyguard
+     *        is showing, or INVALID_DISPLAY if there is no such display. Only meaningful if
+     *        showing is true.
+     */
+    void setLockScreenShown(boolean showing, int secondaryDisplayShowing);
     boolean finishActivityAffinity(in IBinder token);
     // This is not public because you need to be very careful in how you
     // manage your activity to make sure it is always the uid you expect.
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index b38be66..f6d9710 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -625,17 +625,31 @@
         final List<String> zipPaths = new ArrayList<>(10);
         final List<String> libPaths = new ArrayList<>(10);
 
-        final boolean isBundledApp = mApplicationInfo.isSystemApp()
+        boolean isBundledApp = mApplicationInfo.isSystemApp()
                 && !mApplicationInfo.isUpdatedSystemApp();
 
+        // Vendor apks are treated as bundled only when /vendor/lib is in the default search
+        // paths. If not, they are treated as unbundled; access to system libs is limited.
+        // Having /vendor/lib in the default search paths means that all system processes
+        // are allowed to use any vendor library, which in turn means that system is dependent
+        // on vendor partition. In the contrary, not having /vendor/lib in the default search
+        // paths mean that the two partitions are separated and thus we can treat vendor apks
+        // as unbundled.
+        final String defaultSearchPaths = System.getProperty("java.library.path");
+        final boolean treatVendorApkAsUnbundled = !defaultSearchPaths.contains("/vendor/lib");
+        if (mApplicationInfo.getCodePath() != null
+                && mApplicationInfo.getCodePath().startsWith("/vendor/")
+                && treatVendorApkAsUnbundled) {
+            isBundledApp = false;
+        }
+
         makePaths(mActivityThread, isBundledApp, mApplicationInfo, zipPaths, libPaths);
 
         String libraryPermittedPath = mDataDir;
         if (isBundledApp) {
             // This is necessary to grant bundled apps access to
             // libraries located in subdirectories of /system/lib
-            libraryPermittedPath += File.pathSeparator +
-                                    System.getProperty("java.library.path");
+            libraryPermittedPath += File.pathSeparator + defaultSearchPaths;
         }
 
         final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 9511f3f..f25ed27 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -67,6 +67,7 @@
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.SparseArray;
+import android.util.TypedValue;
 import android.view.Gravity;
 import android.view.NotificationHeaderView;
 import android.view.View;
@@ -3898,6 +3899,7 @@
             if (p.title != null) {
                 contentView.setViewVisibility(R.id.title, View.VISIBLE);
                 contentView.setTextViewText(R.id.title, processTextSpans(p.title));
+                updateTextSizePrimary(contentView, R.id.title);
                 if (!p.ambient) {
                     setTextViewColorPrimary(contentView, R.id.title);
                 }
@@ -3909,6 +3911,7 @@
                 int textId = showProgress ? com.android.internal.R.id.text_line_1
                         : com.android.internal.R.id.text;
                 contentView.setTextViewText(textId, processTextSpans(p.text));
+                updateTextSizeSecondary(contentView, textId);
                 if (!p.ambient) {
                     setTextViewColorSecondary(contentView, textId);
                 }
@@ -3920,6 +3923,25 @@
             return contentView;
         }
 
+        private void updateTextSizeSecondary(RemoteViews contentView, int textId) {
+            updateTextSizeColorized(contentView, textId,
+                    com.android.internal.R.dimen.notification_text_size_colorized,
+                    com.android.internal.R.dimen.notification_text_size);
+        }
+
+        private void updateTextSizePrimary(RemoteViews contentView, int textId) {
+            updateTextSizeColorized(contentView, textId,
+                    com.android.internal.R.dimen.notification_title_text_size_colorized,
+                    com.android.internal.R.dimen.notification_title_text_size);
+        }
+
+        private void updateTextSizeColorized(RemoteViews contentView, int textId,
+                int colorizedDimen, int normalDimen) {
+            int size = mContext.getResources().getDimensionPixelSize(isColorized()
+                    ? colorizedDimen : normalDimen);
+            contentView.setTextViewTextSize(textId, TypedValue.COMPLEX_UNIT_PX, size);
+        }
+
         private CharSequence processTextSpans(CharSequence text) {
             if (hasForegroundColor()) {
                 return NotificationColorUtil.clearColorSpans(text);
@@ -5845,6 +5867,7 @@
             builder.setTextViewColorSecondary(contentView, R.id.big_text);
             contentView.setViewVisibility(R.id.big_text,
                     TextUtils.isEmpty(bigTextText) ? View.GONE : View.VISIBLE);
+            builder.updateTextSizeSecondary(contentView, R.id.big_text);
             contentView.setBoolean(R.id.big_text, "setHasImage", builder.mN.hasLargeIcon());
         }
     }
@@ -6178,6 +6201,7 @@
                 contentView.setViewVisibility(rowId, View.VISIBLE);
                 contentView.setTextViewText(rowId, mBuilder.processTextSpans(
                         makeMessageLine(m, mBuilder)));
+                mBuilder.updateTextSizeSecondary(contentView, rowId);
                 mBuilder.setTextViewColorSecondary(contentView, rowId);
 
                 if (contractedMessage == m) {
@@ -6545,6 +6569,7 @@
                     contentView.setViewVisibility(rowIds[i], View.VISIBLE);
                     contentView.setTextViewText(rowIds[i],
                             mBuilder.processTextSpans(mBuilder.processLegacyText(str)));
+                    mBuilder.updateTextSizeSecondary(contentView, rowIds[i]);
                     mBuilder.setTextViewColorSecondary(contentView, rowIds[i]);
                     contentView.setViewPadding(rowIds[i], 0, topPadding, 0, 0);
                     handleInboxImageMargin(contentView, rowIds[i], first);
@@ -8515,8 +8540,15 @@
 
         final StandardTemplateParams fillTextsFrom(Builder b) {
             Bundle extras = b.mN.extras;
-            title = b.processLegacyText(extras.getCharSequence(EXTRA_TITLE), ambient);
-            text = b.processLegacyText(extras.getCharSequence(EXTRA_TEXT), ambient);
+            this.title = b.processLegacyText(extras.getCharSequence(EXTRA_TITLE), ambient);
+
+            // Big text notifications should contain their content when viewed in ambient mode.
+            CharSequence text = extras.getCharSequence(EXTRA_BIG_TEXT);
+            if (!ambient || TextUtils.isEmpty(text)) {
+                text = extras.getCharSequence(EXTRA_TEXT);
+            }
+            this.text = b.processLegacyText(text, ambient);
+
             return this;
         }
     }
diff --git a/core/java/android/app/RemoteInput.java b/core/java/android/app/RemoteInput.java
index 8ab19c0..02a0124 100644
--- a/core/java/android/app/RemoteInput.java
+++ b/core/java/android/app/RemoteInput.java
@@ -33,8 +33,8 @@
  * an intent inside a {@link android.app.PendingIntent} that is sent.
  * Always use {@link RemoteInput.Builder} to create instances of this class.
  * <p class="note"> See
- * <a href="{@docRoot}wear/notifications/remote-input.html">Receiving Voice Input from
- * a Notification</a> for more information on how to use this class.
+ * <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html#direct">Replying
+ * to notifications</a> for more information on how to use this class.
  *
  * <p>The following example adds a {@code RemoteInput} to a {@link Notification.Action},
  * sets the result key as {@code quick_reply}, and sets the label as {@code Quick reply}.
diff --git a/core/java/android/app/VrManager.java b/core/java/android/app/VrManager.java
index 363e20a..5786238 100644
--- a/core/java/android/app/VrManager.java
+++ b/core/java/android/app/VrManager.java
@@ -62,7 +62,10 @@
      * @param callback The callback to register.
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.RESTRICTED_VR_ACCESS,
+            android.Manifest.permission.ACCESS_VR_STATE
+    })
     public void registerVrStateCallback(VrStateCallback callback, @NonNull Handler handler) {
         if (callback == null || mCallbackMap.containsKey(callback)) {
             return;
@@ -88,7 +91,10 @@
      * @param callback The callback to deregister.
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.RESTRICTED_VR_ACCESS,
+            android.Manifest.permission.ACCESS_VR_STATE
+    })
     public void unregisterVrStateCallback(VrStateCallback callback) {
         CallbackEntry entry = mCallbackMap.remove(callback);
         if (entry != null) {
@@ -110,7 +116,10 @@
      * Returns the current VrMode state.
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.ACCESS_VR_STATE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.RESTRICTED_VR_ACCESS,
+            android.Manifest.permission.ACCESS_VR_STATE
+    })
     public boolean getVrModeEnabled() {
         try {
             return mService.getVrModeState();
@@ -124,7 +133,10 @@
      * Returns the current VrMode state.
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.ACCESS_VR_STATE)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.RESTRICTED_VR_ACCESS,
+            android.Manifest.permission.ACCESS_VR_STATE
+    })
     public boolean getPersistentVrModeEnabled() {
         try {
             return mService.getPersistentVrModeEnabled();
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
index 9dfc4b4..4ebef4f 100755
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -125,7 +125,7 @@
 
     private Context mContext;
     private ServiceListener mServiceListener;
-    private IBluetoothA2dpSink mService;
+    private volatile IBluetoothA2dpSink mService;
     private BluetoothAdapter mAdapter;
 
     final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
@@ -239,16 +239,16 @@
      */
     public boolean connect(BluetoothDevice device) {
         if (DBG) log("connect(" + device + ")");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
+        final IBluetoothA2dpSink service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.connect(device);
+                return service.connect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -280,16 +280,16 @@
      */
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
+        final IBluetoothA2dpSink service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.disconnect(device);
+                return service.disconnect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -298,15 +298,16 @@
      */
     public List<BluetoothDevice> getConnectedDevices() {
         if (VDBG) log("getConnectedDevices()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothA2dpSink service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -315,15 +316,16 @@
      */
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         if (VDBG) log("getDevicesMatchingStates()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothA2dpSink service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -332,16 +334,16 @@
      */
     public int getConnectionState(BluetoothDevice device) {
         if (VDBG) log("getState(" + device + ")");
-        if (mService != null && isEnabled()
-            && isValidDevice(device)) {
+        final IBluetoothA2dpSink service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
@@ -358,16 +360,16 @@
      */
           public BluetoothAudioConfig getAudioConfig(BluetoothDevice device) {
         if (VDBG) log("getAudioConfig(" + device + ")");
-        if (mService != null && isEnabled()
-            && isValidDevice(device)) {
+        final IBluetoothA2dpSink service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getAudioConfig(device);
+                return service.getAudioConfig(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return null;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return null;
     }
 
@@ -388,21 +390,21 @@
      */
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        if (mService != null && isEnabled()
-            && isValidDevice(device)) {
-            if (priority != BluetoothProfile.PRIORITY_OFF &&
-                priority != BluetoothProfile.PRIORITY_ON){
+        final IBluetoothA2dpSink service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
+            if (priority != BluetoothProfile.PRIORITY_OFF
+                    && priority != BluetoothProfile.PRIORITY_ON) {
                 return false;
             }
             try {
-                return mService.setPriority(device, priority);
+                return service.setPriority(device, priority);
             } catch (RemoteException e) {
                    Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                    return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
-            return false;
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
+        return false;
     }
 
     /**
@@ -420,16 +422,16 @@
      */
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
-        if (mService != null && isEnabled()
-            && isValidDevice(device)) {
+        final IBluetoothA2dpSink service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getPriority(device);
+                return service.getPriority(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.PRIORITY_OFF;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.PRIORITY_OFF;
     }
 
@@ -441,16 +443,16 @@
      * @param device BluetoothDevice device
      */
     public boolean isA2dpPlaying(BluetoothDevice device) {
-        if (mService != null && isEnabled()
-            && isValidDevice(device)) {
+        final IBluetoothA2dpSink service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.isA2dpPlaying(device);
+                return service.isA2dpPlaying(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -483,7 +485,6 @@
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "Proxy object connected");
             mService = IBluetoothA2dpSink.Stub.asInterface(Binder.allowBlocking(service));
-
             if (mServiceListener != null) {
                 mServiceListener.onServiceConnected(BluetoothProfile.A2DP_SINK,
                         BluetoothA2dpSink.this);
@@ -499,15 +500,11 @@
     };
 
     private boolean isEnabled() {
-       if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
-       return false;
+        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
     }
 
-    private boolean isValidDevice(BluetoothDevice device) {
-       if (device == null) return false;
-
-       if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-       return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
     private static void log(String msg) {
diff --git a/core/java/android/bluetooth/BluetoothAvrcpController.java b/core/java/android/bluetooth/BluetoothAvrcpController.java
index 0261b1b..a04f110 100644
--- a/core/java/android/bluetooth/BluetoothAvrcpController.java
+++ b/core/java/android/bluetooth/BluetoothAvrcpController.java
@@ -20,8 +20,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.media.MediaMetadata;
-import android.media.session.PlaybackState;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -83,7 +81,7 @@
 
     private Context mContext;
     private ServiceListener mServiceListener;
-    private IBluetoothAvrcpController mService;
+    private volatile IBluetoothAvrcpController mService;
     private BluetoothAdapter mAdapter;
 
     final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
@@ -180,15 +178,16 @@
      */
     public List<BluetoothDevice> getConnectedDevices() {
         if (VDBG) log("getConnectedDevices()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothAvrcpController service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -197,15 +196,16 @@
      */
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         if (VDBG) log("getDevicesMatchingStates()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothAvrcpController service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -214,16 +214,16 @@
      */
     public int getConnectionState(BluetoothDevice device) {
         if (VDBG) log("getState(" + device + ")");
-        if (mService != null && isEnabled()
-            && isValidDevice(device)) {
+        final IBluetoothAvrcpController service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
@@ -235,9 +235,10 @@
     public BluetoothAvrcpPlayerSettings getPlayerSettings(BluetoothDevice device) {
         if (DBG) Log.d(TAG, "getPlayerSettings");
         BluetoothAvrcpPlayerSettings settings = null;
-        if (mService != null && isEnabled()) {
+        final IBluetoothAvrcpController service = mService;
+        if (service != null && isEnabled()) {
             try {
-                settings = mService.getPlayerSettings(device);
+                settings = service.getPlayerSettings(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Error talking to BT service in getMetadata() " + e);
                 return null;
@@ -252,15 +253,16 @@
      */
     public boolean setPlayerApplicationSetting(BluetoothAvrcpPlayerSettings plAppSetting) {
         if (DBG) Log.d(TAG, "setPlayerApplicationSetting");
-        if (mService != null && isEnabled()) {
+        final IBluetoothAvrcpController service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.setPlayerApplicationSetting(plAppSetting);
+                return service.setPlayerApplicationSetting(plAppSetting);
             } catch (RemoteException e) {
                 Log.e(TAG, "Error talking to BT service in setPlayerApplicationSetting() " + e);
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -269,24 +271,25 @@
      * possible keycode values: next_grp, previous_grp defined above
      */
     public void sendGroupNavigationCmd(BluetoothDevice device, int keyCode, int keyState) {
-        Log.d(TAG, "sendGroupNavigationCmd dev = " + device + " key " + keyCode + " State = " + keyState);
-        if (mService != null && isEnabled()) {
+        Log.d(TAG, "sendGroupNavigationCmd dev = " + device + " key " + keyCode + " State = "
+                + keyState);
+        final IBluetoothAvrcpController service = mService;
+        if (service != null && isEnabled()) {
             try {
-                mService.sendGroupNavigationCmd(device, keyCode, keyState);
+                service.sendGroupNavigationCmd(device, keyCode, keyState);
                 return;
             } catch (RemoteException e) {
                 Log.e(TAG, "Error talking to BT service in sendGroupNavigationCmd()", e);
                 return;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
     }
 
     private final ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "Proxy object connected");
             mService = IBluetoothAvrcpController.Stub.asInterface(Binder.allowBlocking(service));
-
             if (mServiceListener != null) {
                 mServiceListener.onServiceConnected(BluetoothProfile.AVRCP_CONTROLLER,
                         BluetoothAvrcpController.this);
@@ -302,15 +305,11 @@
     };
 
     private boolean isEnabled() {
-       if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
-       return false;
+        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
     }
 
-    private boolean isValidDevice(BluetoothDevice device) {
-       if (device == null) return false;
-
-       if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-       return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
     private static void log(String msg) {
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index a206b53..98cd319 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -23,10 +23,9 @@
 import android.annotation.SystemApi;
 import android.content.Context;
 import android.os.Handler;
-import android.os.Looper;
 import android.os.Parcel;
-import android.os.Parcelable;
 import android.os.ParcelUuid;
+import android.os.Parcelable;
 import android.os.Process;
 import android.os.RemoteException;
 import android.util.Log;
@@ -683,7 +682,7 @@
      * getService() called.
      * TODO: Unify implementation of sService amongst BluetoothFoo API's
      */
-    private static IBluetooth sService;
+    private static volatile IBluetooth sService;
 
     private final String mAddress;
 
@@ -803,13 +802,16 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
     public String getName() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot get Remote Device name");
             return null;
         }
         try {
-            return sService.getRemoteName(this);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            return service.getRemoteName(this);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
         return null;
     }
 
@@ -822,13 +824,16 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
     public int getType() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot get Remote Device type");
             return DEVICE_TYPE_UNKNOWN;
         }
         try {
-            return sService.getRemoteType(this);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            return service.getRemoteType(this);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
         return DEVICE_TYPE_UNKNOWN;
     }
 
@@ -840,13 +845,16 @@
      * @hide
      */
     public String getAlias() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot get Remote Device Alias");
             return null;
         }
         try {
-            return sService.getRemoteAlias(this);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            return service.getRemoteAlias(this);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
         return null;
     }
 
@@ -861,13 +869,16 @@
      * @hide
      */
     public boolean setAlias(String alias) {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot set Remote Device name");
             return false;
         }
         try {
-            return sService.setRemoteAlias(this, alias);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            return service.setRemoteAlias(this, alias);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
         return false;
     }
 
@@ -899,13 +910,16 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
     public int getBatteryLevel() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "Bluetooth disabled. Cannot get remote device battery level");
             return BATTERY_LEVEL_UNKNOWN;
         }
         try {
-            return sService.getBatteryLevel(this);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            return service.getBatteryLevel(this);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
         return BATTERY_LEVEL_UNKNOWN;
     }
 
@@ -921,16 +935,19 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public boolean createBond() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
             return false;
         }
         try {
-            Log.i(TAG, "createBond() for device " + getAddress() +
-                    " called by pid: " + Process.myPid() +
-                    " tid: " + Process.myTid());
-            return sService.createBond(this, TRANSPORT_AUTO);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            Log.i(TAG, "createBond() for device " + getAddress()
+                    + " called by pid: " + Process.myPid()
+                    + " tid: " + Process.myTid());
+            return service.createBond(this, TRANSPORT_AUTO);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
         return false;
     }
 
@@ -951,7 +968,8 @@
      * @hide
      */
     public boolean createBond(int transport) {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
             return false;
         }
@@ -960,11 +978,13 @@
             throw new IllegalArgumentException(transport + " is not a valid Bluetooth transport");
         }
         try {
-            Log.i(TAG, "createBond() for device " + getAddress() +
-                    " called by pid: " + Process.myPid() +
-                    " tid: " + Process.myTid());
-            return sService.createBond(this, transport);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            Log.i(TAG, "createBond() for device " + getAddress()
+                    + " called by pid: " + Process.myPid()
+                    + " tid: " + Process.myTid());
+            return service.createBond(this, transport);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
         return false;
     }
 
@@ -988,17 +1008,31 @@
      * @hide
      */
     public boolean createBondOutOfBand(int transport, OobData oobData) {
+        final IBluetooth service = sService;
+        if (service == null) {
+            Log.w(TAG, "BT not enabled, createBondOutOfBand failed");
+            return false;
+        }
         try {
-            return sService.createBondOutOfBand(this, transport, oobData);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            return service.createBondOutOfBand(this, transport, oobData);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
         return false;
     }
 
     /** @hide */
     public boolean isBondingInitiatedLocally() {
+        final IBluetooth service = sService;
+        if (service == null) {
+            Log.w(TAG, "BT not enabled, isBondingInitiatedLocally failed");
+            return false;
+        }
         try {
-            return sService.isBondingInitiatedLocally(this);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            return service.isBondingInitiatedLocally(this);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
         return false;
     }
 
@@ -1032,16 +1066,19 @@
      * @hide
      */
     public boolean cancelBondProcess() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot cancel Remote Device bond");
             return false;
         }
         try {
-            Log.i(TAG, "cancelBondProcess() for device " + getAddress() +
-                    " called by pid: " + Process.myPid() +
-                    " tid: " + Process.myTid());
-            return sService.cancelBondProcess(this);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            Log.i(TAG, "cancelBondProcess() for device " + getAddress()
+                    + " called by pid: " + Process.myPid()
+                    + " tid: " + Process.myTid());
+            return service.cancelBondProcess(this);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
         return false;
     }
 
@@ -1056,16 +1093,19 @@
      * @hide
      */
     public boolean removeBond() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot remove Remote Device bond");
             return false;
         }
         try {
-            Log.i(TAG, "removeBond() for device " + getAddress() +
-                    " called by pid: " + Process.myPid() +
-                    " tid: " + Process.myTid());
-            return sService.removeBond(this);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            Log.i(TAG, "removeBond() for device " + getAddress()
+                    + " called by pid: " + Process.myPid()
+                    + " tid: " + Process.myTid());
+            return service.removeBond(this);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
         return false;
     }
 
@@ -1080,18 +1120,15 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
     public int getBondState() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot get bond state");
             return BOND_NONE;
         }
         try {
-            return sService.getBondState(this);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
-        catch (NullPointerException npe) {
-            // Handle case where bluetooth service proxy
-            // is already null.
-            Log.e(TAG, "NullPointerException for getBondState() of device ("+
-                getAddress()+")", npe);
+            return service.getBondState(this);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
         }
         return BOND_NONE;
     }
@@ -1105,12 +1142,13 @@
      */
     @SystemApi
     public boolean isConnected() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             // BT is not enabled, we cannot be connected.
             return false;
         }
         try {
-            return sService.getConnectionState(this) != CONNECTION_STATE_DISCONNECTED;
+            return service.getConnectionState(this) != CONNECTION_STATE_DISCONNECTED;
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
             return false;
@@ -1127,12 +1165,13 @@
      */
     @SystemApi
     public boolean isEncrypted() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             // BT is not enabled, we cannot be connected.
             return false;
         }
         try {
-            return sService.getConnectionState(this) > CONNECTION_STATE_CONNECTED;
+            return service.getConnectionState(this) > CONNECTION_STATE_CONNECTED;
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
             return false;
@@ -1146,12 +1185,13 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
     public BluetoothClass getBluetoothClass() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot get Bluetooth Class");
             return null;
         }
         try {
-            int classInt = sService.getRemoteClass(this);
+            int classInt = service.getRemoteClass(this);
             if (classInt == BluetoothClass.ERROR) return null;
             return new BluetoothClass(classInt);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
@@ -1170,75 +1210,82 @@
      *         or null on error
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-     public ParcelUuid[] getUuids() {
-         if (sService == null || isBluetoothEnabled() == false) {
+    public ParcelUuid[] getUuids() {
+        final IBluetooth service = sService;
+        if (service == null || !isBluetoothEnabled()) {
             Log.e(TAG, "BT not enabled. Cannot get remote device Uuids");
              return null;
          }
         try {
-            return sService.getRemoteUuids(this);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            return service.getRemoteUuids(this);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
         return null;
     }
 
-     /**
-      * Perform a service discovery on the remote device to get the UUIDs supported.
-      *
-      * <p>This API is asynchronous and {@link #ACTION_UUID} intent is sent,
-      * with the UUIDs supported by the remote end. If there is an error
-      * in getting the SDP records or if the process takes a long time,
-      * {@link #ACTION_UUID} intent is sent with the UUIDs that is currently
-      * present in the cache. Clients should use the {@link #getUuids} to get UUIDs
-      * if service discovery is not to be performed.
-      *
-      * @return False if the sanity check fails, True if the process
-      *               of initiating an ACL connection to the remote device
-      *               was started.
-      */
-     @RequiresPermission(Manifest.permission.BLUETOOTH)
-     public boolean fetchUuidsWithSdp() {
-        IBluetooth service = sService;
-        if (service == null || isBluetoothEnabled() == false) {
+    /**
+     * Perform a service discovery on the remote device to get the UUIDs supported.
+     *
+     * <p>This API is asynchronous and {@link #ACTION_UUID} intent is sent,
+     * with the UUIDs supported by the remote end. If there is an error
+     * in getting the SDP records or if the process takes a long time,
+     * {@link #ACTION_UUID} intent is sent with the UUIDs that is currently
+     * present in the cache. Clients should use the {@link #getUuids} to get UUIDs
+     * if service discovery is not to be performed.
+     *
+     * @return False if the sanity check fails, True if the process of initiating an ACL connection
+     * to the remote device was started.
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public boolean fetchUuidsWithSdp() {
+        final IBluetooth service = sService;
+        if (service == null || !isBluetoothEnabled()) {
             Log.e(TAG, "BT not enabled. Cannot fetchUuidsWithSdp");
             return false;
         }
         try {
             return service.fetchRemoteUuids(this);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
-            return false;
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
+        return false;
     }
 
-     /**
-      * Perform a service discovery on the remote device to get the SDP records associated
-      * with the specified UUID.
-      *
-      * <p>This API is asynchronous and {@link #ACTION_SDP_RECORD} intent is sent,
-      * with the SDP records found on the remote end. If there is an error
-      * in getting the SDP records or if the process takes a long time,
-      * {@link #ACTION_SDP_RECORD} intent is sent with an status value in
-      * {@link #EXTRA_SDP_SEARCH_STATUS} different from 0.
-      * Detailed status error codes can be found by members of the Bluetooth package in
-      * the AbstractionLayer class.
-      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
-      * The SDP record data will be stored in the intent as {@link #EXTRA_SDP_RECORD}.
-      * The object type will match one of the SdpXxxRecord types, depending on the UUID searched
-      * for.
-      *
-      * @return False if the sanity check fails, True if the process
-      *               of initiating an ACL connection to the remote device
-      *               was started.
-      */
-     /** @hide */
-     public boolean sdpSearch(ParcelUuid uuid) {
-         if (sService == null) {
-             Log.e(TAG, "BT not enabled. Cannot query remote device sdp records");
-             return false;
-         }
-         try {
-             return sService.sdpSearch(this,uuid);
-         } catch (RemoteException e) {Log.e(TAG, "", e);}
-         return false;
-     }
+    /**
+     * Perform a service discovery on the remote device to get the SDP records associated
+     * with the specified UUID.
+     *
+     * <p>This API is asynchronous and {@link #ACTION_SDP_RECORD} intent is sent,
+     * with the SDP records found on the remote end. If there is an error
+     * in getting the SDP records or if the process takes a long time,
+     * {@link #ACTION_SDP_RECORD} intent is sent with an status value in
+     * {@link #EXTRA_SDP_SEARCH_STATUS} different from 0.
+     * Detailed status error codes can be found by members of the Bluetooth package in
+     * the AbstractionLayer class.
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
+     * The SDP record data will be stored in the intent as {@link #EXTRA_SDP_RECORD}.
+     * The object type will match one of the SdpXxxRecord types, depending on the UUID searched
+     * for.
+     *
+     * @return False if the sanity check fails, True if the process
+     *               of initiating an ACL connection to the remote device
+     *               was started.
+     */
+    /** @hide */
+    public boolean sdpSearch(ParcelUuid uuid) {
+        final IBluetooth service = sService;
+        if (service == null) {
+            Log.e(TAG, "BT not enabled. Cannot query remote device sdp records");
+            return false;
+        }
+        try {
+            return service.sdpSearch(this, uuid);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
+        return false;
+    }
 
     /**
      * Set the pin during pairing when the pairing method is {@link #PAIRING_VARIANT_PIN}
@@ -1248,13 +1295,16 @@
      *         false for error
      */
     public boolean setPin(byte[] pin) {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot set Remote Device pin");
             return false;
         }
         try {
-            return sService.setPin(this, true, pin.length, pin);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            return service.setPin(this, true, pin.length, pin);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
         return false;
     }
 
@@ -1276,13 +1326,16 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
     public boolean setPairingConfirmation(boolean confirm) {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot set pairing confirmation");
             return false;
         }
         try {
-            return sService.setPairingConfirmation(this, confirm);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            return service.setPairingConfirmation(this, confirm);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
         return false;
     }
 
@@ -1298,13 +1351,16 @@
 
     /** @hide */
     public boolean cancelPairingUserInput() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot create pairing user input");
             return false;
         }
         try {
-            return sService.cancelBondProcess(this);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}
+            return service.cancelBondProcess(this);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
         return false;
     }
 
@@ -1334,11 +1390,12 @@
      * @hide
      */
     public int getPhonebookAccessPermission() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             return ACCESS_UNKNOWN;
         }
         try {
-            return sService.getPhonebookAccessPermission(this);
+            return service.getPhonebookAccessPermission(this);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1354,11 +1411,12 @@
      * @hide
      */
     public boolean setPhonebookAccessPermission(int value) {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             return false;
         }
         try {
-            return sService.setPhonebookAccessPermission(this, value);
+            return service.setPhonebookAccessPermission(this, value);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1372,11 +1430,12 @@
      * @hide
      */
     public int getMessageAccessPermission() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             return ACCESS_UNKNOWN;
         }
         try {
-            return sService.getMessageAccessPermission(this);
+            return service.getMessageAccessPermission(this);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1392,11 +1451,12 @@
      * @hide
      */
     public boolean setMessageAccessPermission(int value) {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             return false;
         }
         try {
-            return sService.setMessageAccessPermission(this, value);
+            return service.setMessageAccessPermission(this, value);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1410,11 +1470,12 @@
      * @hide
      */
     public int getSimAccessPermission() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             return ACCESS_UNKNOWN;
         }
         try {
-            return sService.getSimAccessPermission(this);
+            return service.getSimAccessPermission(this);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1430,11 +1491,12 @@
      * @hide
      */
     public boolean setSimAccessPermission(int value) {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             return false;
         }
         try {
-            return sService.setSimAccessPermission(this, value);
+            return service.setSimAccessPermission(this, value);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 678159b..b596dd6 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -42,7 +42,7 @@
     private static final boolean VDBG = false;
 
     private IBluetoothGatt mService;
-    private BluetoothGattCallback mCallback;
+    private volatile BluetoothGattCallback mCallback;
     private Handler mHandler;
     private int mClientIf;
     private BluetoothDevice mDevice;
@@ -159,8 +159,9 @@
                     runOrQueueCallback(new Runnable() {
                         @Override
                         public void run() {
-                            if (mCallback != null) {
-                                mCallback.onConnectionStateChange(BluetoothGatt.this, GATT_FAILURE,
+                            final BluetoothGattCallback callback = mCallback;
+                            if (callback != null) {
+                                callback.onConnectionStateChange(BluetoothGatt.this, GATT_FAILURE,
                                                   BluetoothProfile.STATE_DISCONNECTED);
                             }
                         }
@@ -194,8 +195,9 @@
                 runOrQueueCallback(new Runnable() {
                     @Override
                     public void run() {
-                        if (mCallback != null) {
-                            mCallback.onPhyUpdate(BluetoothGatt.this, txPhy, rxPhy, status);
+                        final BluetoothGattCallback callback = mCallback;
+                        if (callback != null) {
+                            callback.onPhyUpdate(BluetoothGatt.this, txPhy, rxPhy, status);
                         }
                     }
                 });
@@ -216,8 +218,9 @@
                 runOrQueueCallback(new Runnable() {
                     @Override
                     public void run() {
-                        if (mCallback != null) {
-                            mCallback.onPhyRead(BluetoothGatt.this, txPhy, rxPhy, status);
+                        final BluetoothGattCallback callback = mCallback;
+                        if (callback != null) {
+                            callback.onPhyRead(BluetoothGatt.this, txPhy, rxPhy, status);
                         }
                     }
                 });
@@ -241,8 +244,9 @@
                 runOrQueueCallback(new Runnable() {
                     @Override
                     public void run() {
-                        if (mCallback != null) {
-                            mCallback.onConnectionStateChange(BluetoothGatt.this, status,
+                        final BluetoothGattCallback callback = mCallback;
+                        if (callback != null) {
+                            callback.onConnectionStateChange(BluetoothGatt.this, status,
                                                               profileState);
                         }
                     }
@@ -303,8 +307,9 @@
                 runOrQueueCallback(new Runnable() {
                     @Override
                     public void run() {
-                        if (mCallback != null) {
-                            mCallback.onServicesDiscovered(BluetoothGatt.this, status);
+                        final BluetoothGattCallback callback = mCallback;
+                        if (callback != null) {
+                            callback.onServicesDiscovered(BluetoothGatt.this, status);
                         }
                     }
                 });
@@ -350,13 +355,13 @@
                     return;
                 }
 
-                if (status == 0) characteristic.setValue(value);
-
                 runOrQueueCallback(new Runnable() {
                     @Override
                     public void run() {
-                        if (mCallback != null) {
-                            mCallback.onCharacteristicRead(BluetoothGatt.this, characteristic,
+                        final BluetoothGattCallback callback = mCallback;
+                        if (callback != null) {
+                            if (status == 0) characteristic.setValue(value);
+                            callback.onCharacteristicRead(BluetoothGatt.this, characteristic,
                                                            status);
                         }
                     }
@@ -404,8 +409,9 @@
                 runOrQueueCallback(new Runnable() {
                     @Override
                     public void run() {
-                        if (mCallback != null) {
-                            mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic,
+                        final BluetoothGattCallback callback = mCallback;
+                        if (callback != null) {
+                            callback.onCharacteristicWrite(BluetoothGatt.this, characteristic,
                                                             status);
                         }
                     }
@@ -428,13 +434,13 @@
                 BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice, handle);
                 if (characteristic == null) return;
 
-                characteristic.setValue(value);
-
                 runOrQueueCallback(new Runnable() {
                     @Override
                     public void run() {
-                        if (mCallback != null) {
-                            mCallback.onCharacteristicChanged(BluetoothGatt.this, characteristic);
+                        final BluetoothGattCallback callback = mCallback;
+                        if (callback != null) {
+                            characteristic.setValue(value);
+                            callback.onCharacteristicChanged(BluetoothGatt.this, characteristic);
                         }
                     }
                 });
@@ -459,7 +465,6 @@
                 BluetoothGattDescriptor descriptor = getDescriptorById(mDevice, handle);
                 if (descriptor == null) return;
 
-                if (status == 0) descriptor.setValue(value);
 
                 if ((status == GATT_INSUFFICIENT_AUTHENTICATION
                   || status == GATT_INSUFFICIENT_ENCRYPTION)
@@ -480,8 +485,10 @@
                 runOrQueueCallback(new Runnable() {
                     @Override
                     public void run() {
-                        if (mCallback != null) {
-                            mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
+                        final BluetoothGattCallback callback = mCallback;
+                        if (callback != null) {
+                            if (status == 0) descriptor.setValue(value);
+                            callback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
                         }
                     }
                 });
@@ -526,8 +533,9 @@
                 runOrQueueCallback(new Runnable() {
                     @Override
                     public void run() {
-                        if (mCallback != null) {
-                            mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status);
+                        final BluetoothGattCallback callback = mCallback;
+                        if (callback != null) {
+                            callback.onDescriptorWrite(BluetoothGatt.this, descriptor, status);
                         }
                     }
                 });
@@ -552,8 +560,9 @@
                 runOrQueueCallback(new Runnable() {
                     @Override
                     public void run() {
-                        if (mCallback != null) {
-                           mCallback.onReliableWriteCompleted(BluetoothGatt.this, status);
+                        final BluetoothGattCallback callback = mCallback;
+                        if (callback != null) {
+                            callback.onReliableWriteCompleted(BluetoothGatt.this, status);
                         }
                     }
                 });
@@ -573,8 +582,9 @@
                 runOrQueueCallback(new Runnable() {
                     @Override
                     public void run() {
-                        if (mCallback != null) {
-                            mCallback.onReadRemoteRssi(BluetoothGatt.this, rssi, status);
+                        final BluetoothGattCallback callback = mCallback;
+                        if (callback != null) {
+                            callback.onReadRemoteRssi(BluetoothGatt.this, rssi, status);
                         }
                     }
                 });
@@ -595,8 +605,9 @@
                 runOrQueueCallback(new Runnable() {
                     @Override
                     public void run() {
-                        if (mCallback != null) {
-                            mCallback.onMtuChanged(BluetoothGatt.this, mtu, status);
+                        final BluetoothGattCallback callback = mCallback;
+                        if (callback != null) {
+                            callback.onMtuChanged(BluetoothGatt.this, mtu, status);
                         }
                     }
                 });
@@ -619,8 +630,9 @@
                 runOrQueueCallback(new Runnable() {
                     @Override
                     public void run() {
-                        if (mCallback != null) {
-                            mCallback.onConnectionUpdated(BluetoothGatt.this, interval, latency,
+                        final BluetoothGattCallback callback = mCallback;
+                        if (callback != null) {
+                            callback.onConnectionUpdated(BluetoothGatt.this, interval, latency,
                                                           timeout, status);
                         }
                     }
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index c84643f..500cba3 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -298,7 +298,7 @@
 
     private Context mContext;
     private ServiceListener mServiceListener;
-    private IBluetoothHeadset mService;
+    private volatile IBluetoothHeadset mService;
     private BluetoothAdapter mAdapter;
 
     final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
@@ -411,16 +411,16 @@
      */
     public boolean connect(BluetoothDevice device) {
         if (DBG) log("connect(" + device + ")");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.connect(device);
+                return service.connect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -452,16 +452,16 @@
      */
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.disconnect(device);
+                return service.disconnect(device);
             } catch (RemoteException e) {
               Log.e(TAG, Log.getStackTraceString(new Throwable()));
               return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -470,15 +470,16 @@
      */
     public List<BluetoothDevice> getConnectedDevices() {
         if (VDBG) log("getConnectedDevices()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -487,15 +488,16 @@
      */
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         if (VDBG) log("getDevicesMatchingStates()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -504,16 +506,16 @@
      */
     public int getConnectionState(BluetoothDevice device) {
         if (VDBG) log("getConnectionState(" + device + ")");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
@@ -534,20 +536,20 @@
      */
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
-            if (priority != BluetoothProfile.PRIORITY_OFF &&
-                priority != BluetoothProfile.PRIORITY_ON) {
-              return false;
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
+            if (priority != BluetoothProfile.PRIORITY_OFF
+                    && priority != BluetoothProfile.PRIORITY_ON) {
+                return false;
             }
             try {
-                return mService.setPriority(device, priority);
+                return service.setPriority(device, priority);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -566,16 +568,16 @@
      */
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getPriority(device);
+                return service.getPriority(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return PRIORITY_OFF;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return PRIORITY_OFF;
     }
 
@@ -602,15 +604,15 @@
      */
     public boolean startVoiceRecognition(BluetoothDevice device) {
         if (DBG) log("startVoiceRecognition()");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.startVoiceRecognition(device);
+                return service.startVoiceRecognition(device);
             } catch (RemoteException e) {
                 Log.e(TAG,  Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -626,15 +628,15 @@
      */
     public boolean stopVoiceRecognition(BluetoothDevice device) {
         if (DBG) log("stopVoiceRecognition()");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.stopVoiceRecognition(device);
+                return service.stopVoiceRecognition(device);
             } catch (RemoteException e) {
                 Log.e(TAG,  Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -649,15 +651,15 @@
      */
     public boolean isAudioConnected(BluetoothDevice device) {
         if (VDBG) log("isAudioConnected()");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-              return mService.isAudioConnected(device);
+                return service.isAudioConnected(device);
             } catch (RemoteException e) {
               Log.e(TAG,  Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -677,15 +679,15 @@
      */
     public int getBatteryUsageHint(BluetoothDevice device) {
         if (VDBG) log("getBatteryUsageHint()");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getBatteryUsageHint(device);
+                return service.getBatteryUsageHint(device);
             } catch (RemoteException e) {
                 Log.e(TAG,  Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return -1;
     }
 
@@ -708,10 +710,13 @@
      */
     public boolean acceptIncomingConnect(BluetoothDevice device) {
         if (DBG) log("acceptIncomingConnect");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.acceptIncomingConnect(device);
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+                return service.acceptIncomingConnect(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
         } else {
             Log.w(TAG, "Proxy not attached to service");
             if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
@@ -725,10 +730,13 @@
      */
     public boolean rejectIncomingConnect(BluetoothDevice device) {
         if (DBG) log("rejectIncomingConnect");
-        if (mService != null) {
+        final IBluetoothHeadset service = mService;
+        if (service != null) {
             try {
-                return mService.rejectIncomingConnect(device);
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+                return service.rejectIncomingConnect(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
         } else {
             Log.w(TAG, "Proxy not attached to service");
             if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
@@ -744,10 +752,13 @@
      */
     public int getAudioState(BluetoothDevice device) {
         if (VDBG) log("getAudioState");
-        if (mService != null && !isDisabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && !isDisabled()) {
             try {
-                return mService.getAudioState(device);
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+                return service.getAudioState(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
         } else {
             Log.w(TAG, "Proxy not attached to service");
             if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
@@ -768,10 +779,13 @@
      */
     public void setAudioRouteAllowed(boolean allowed) {
         if (VDBG) log("setAudioRouteAllowed");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                mService.setAudioRouteAllowed(allowed);
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+                service.setAudioRouteAllowed(allowed);
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
         } else {
             Log.w(TAG, "Proxy not attached to service");
             if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
@@ -786,10 +800,13 @@
      */
     public boolean getAudioRouteAllowed() {
         if (VDBG) log("getAudioRouteAllowed");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getAudioRouteAllowed();
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+                return service.getAudioRouteAllowed();
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
         } else {
             Log.w(TAG, "Proxy not attached to service");
             if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
@@ -807,9 +824,10 @@
      */
     public void setForceScoAudio(boolean forced) {
         if (VDBG) log("setForceScoAudio " + String.valueOf(forced));
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                mService.setForceScoAudio(forced);
+                service.setForceScoAudio(forced);
             } catch (RemoteException e) {
               Log.e(TAG, e.toString());
             }
@@ -830,14 +848,15 @@
      */
     public boolean isAudioOn() {
         if (VDBG) log("isAudioOn()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-              return mService.isAudioOn();
+                return service.isAudioOn();
             } catch (RemoteException e) {
               Log.e(TAG,  Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
 
     }
@@ -852,9 +871,10 @@
      * @hide
      */
     public boolean connectAudio() {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.connectAudio();
+                return service.connectAudio();
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -875,9 +895,10 @@
      * @hide
      */
     public boolean disconnectAudio() {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.disconnectAudio();
+                return service.disconnectAudio();
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -901,9 +922,10 @@
      */
     public boolean startScoUsingVirtualVoiceCall(BluetoothDevice device) {
         if (DBG) log("startScoUsingVirtualVoiceCall()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.startScoUsingVirtualVoiceCall(device);
+                return service.startScoUsingVirtualVoiceCall(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -924,9 +946,10 @@
      */
     public boolean stopScoUsingVirtualVoiceCall(BluetoothDevice device) {
         if (DBG) log("stopScoUsingVirtualVoiceCall()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.stopScoUsingVirtualVoiceCall(device);
+                return service.stopScoUsingVirtualVoiceCall(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -946,10 +969,11 @@
      * @hide
      */
     public void phoneStateChanged(int numActive, int numHeld, int callState, String number,
-                                  int type) {
-        if (mService != null && isEnabled()) {
+            int type) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                mService.phoneStateChanged(numActive, numHeld, callState, number, type);
+                service.phoneStateChanged(numActive, numHeld, callState, number, type);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -965,10 +989,11 @@
      * @hide
      */
     public void clccResponse(int index, int direction, int status, int mode, boolean mpty,
-                             String number, int type) {
-        if (mService != null && isEnabled()) {
+            String number, int type) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                mService.clccResponse(index, direction, status, mode, mpty, number, type);
+                service.clccResponse(index, direction, status, mode, mpty, number, type);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -1004,15 +1029,15 @@
         if (command == null) {
             throw new IllegalArgumentException("command is null");
         }
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.sendVendorSpecificResultCode(device, command, arg);
+                return service.sendVendorSpecificResultCode(device, command, arg);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) {
+        if (service == null) {
             Log.w(TAG, "Proxy not attached to service");
         }
         return false;
@@ -1027,9 +1052,10 @@
      * @hide
      */
     public boolean enableWBS() {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.enableWBS();
+                return service.enableWBS();
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -1049,9 +1075,10 @@
      * @hide
      */
     public boolean disableWBS() {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.disableWBS();
+                return service.disableWBS();
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -1078,16 +1105,17 @@
      * Send Headset the BIND response from AG to report change in the status of the
      * HF indicators to the headset
      *
-     * @param ind_id Assigned Number of the indicator (defined by SIG)
-     * @param ind_status
+     * @param indId Assigned Number of the indicator (defined by SIG)
+     * @param indStatus
      * possible values- false-Indicator is disabled, no value changes shall be sent for this indicator
      *                  true-Indicator is enabled, value changes may be sent for this indicator
      * @hide
      */
-    public void bindResponse(int ind_id, boolean ind_status) {
-        if (mService != null && isEnabled()) {
+    public void bindResponse(int indId, boolean indStatus) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                mService.bindResponse(ind_id, ind_status);
+                service.bindResponse(indId, indStatus);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -1116,20 +1144,15 @@
     };
 
     private boolean isEnabled() {
-       if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
-       return false;
+        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
     }
 
     private boolean isDisabled() {
-       if (mAdapter.getState() == BluetoothAdapter.STATE_OFF) return true;
-       return false;
+        return mAdapter.getState() == BluetoothAdapter.STATE_OFF;
     }
 
-    private boolean isValidDevice(BluetoothDevice device) {
-       if (device == null) return false;
-
-       if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-       return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
     private static void log(String msg) {
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
index 544b3b95..73a16de 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -28,7 +28,6 @@
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.UUID;
 
 /**
  * Public API to control Hands Free Profile (HFP role only).
@@ -77,8 +76,8 @@
      * Intent sent whenever audio state changes.
      *
      * <p>It includes two mandatory extras:
-     * {@link BluetoothProfile.EXTRA_STATE},
-     * {@link BluetoothProfile.EXTRA_PREVIOUS_STATE},
+     * {@link BluetoothProfile#EXTRA_STATE},
+     * {@link BluetoothProfile#EXTRA_PREVIOUS_STATE},
      * with possible values:
      * {@link #STATE_AUDIO_CONNECTING},
      * {@link #STATE_AUDIO_CONNECTED},
@@ -368,7 +367,7 @@
 
     private Context mContext;
     private ServiceListener mServiceListener;
-    private IBluetoothHeadsetClient mService;
+    private volatile IBluetoothHeadsetClient mService;
     private BluetoothAdapter mAdapter;
 
     final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
@@ -480,16 +479,16 @@
      */
     public boolean connect(BluetoothDevice device) {
         if (DBG) log("connect(" + device + ")");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.connect(device);
+                return service.connect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -504,16 +503,16 @@
      */
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.disconnect(device);
+                return service.disconnect(device);
             } catch (RemoteException e) {
               Log.e(TAG, Log.getStackTraceString(new Throwable()));
               return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -525,15 +524,16 @@
     @Override
     public List<BluetoothDevice> getConnectedDevices() {
         if (VDBG) log("getConnectedDevices()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -548,15 +548,16 @@
     @Override
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         if (VDBG) log("getDevicesMatchingStates()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -569,16 +570,16 @@
     @Override
     public int getConnectionState(BluetoothDevice device) {
         if (VDBG) log("getConnectionState(" + device + ")");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
@@ -589,20 +590,20 @@
      */
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
-            if (priority != BluetoothProfile.PRIORITY_OFF &&
-                    priority != BluetoothProfile.PRIORITY_ON) {
-              return false;
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
+            if (priority != BluetoothProfile.PRIORITY_OFF
+                    && priority != BluetoothProfile.PRIORITY_ON) {
+                return false;
             }
             try {
-                return mService.setPriority(device, priority);
+                return service.setPriority(device, priority);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -611,16 +612,16 @@
      */
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getPriority(device);
+                return service.getPriority(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return PRIORITY_OFF;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return PRIORITY_OFF;
     }
 
@@ -639,15 +640,15 @@
      */
     public boolean startVoiceRecognition(BluetoothDevice device) {
         if (DBG) log("startVoiceRecognition()");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.startVoiceRecognition(device);
+                return service.startVoiceRecognition(device);
             } catch (RemoteException e) {
                 Log.e(TAG,  Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -666,15 +667,15 @@
      */
     public boolean stopVoiceRecognition(BluetoothDevice device) {
         if (DBG) log("stopVoiceRecognition()");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.stopVoiceRecognition(device);
+                return service.stopVoiceRecognition(device);
             } catch (RemoteException e) {
                 Log.e(TAG,  Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -686,15 +687,15 @@
      */
     public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
         if (DBG) log("getCurrentCalls()");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getCurrentCalls(device);
+                return service.getCurrentCalls(device);
             } catch (RemoteException e) {
                 Log.e(TAG,  Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return null;
     }
 
@@ -707,15 +708,15 @@
      */
     public Bundle getCurrentAgEvents(BluetoothDevice device) {
         if (DBG) log("getCurrentCalls()");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getCurrentAgEvents(device);
+                return service.getCurrentAgEvents(device);
             } catch (RemoteException e) {
                 Log.e(TAG,  Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return null;
     }
 
@@ -733,15 +734,15 @@
      */
     public boolean acceptCall(BluetoothDevice device, int flag) {
         if (DBG) log("acceptCall()");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.acceptCall(device, flag);
+                return service.acceptCall(device, flag);
             } catch (RemoteException e) {
                 Log.e(TAG,  Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -756,15 +757,15 @@
      */
     public boolean holdCall(BluetoothDevice device) {
         if (DBG) log("holdCall()");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.holdCall(device);
+                return service.holdCall(device);
             } catch (RemoteException e) {
                 Log.e(TAG,  Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -783,15 +784,15 @@
      */
     public boolean rejectCall(BluetoothDevice device) {
         if (DBG) log("rejectCall()");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.rejectCall(device);
+                return service.rejectCall(device);
             } catch (RemoteException e) {
                 Log.e(TAG,  Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -802,7 +803,7 @@
      *
      * @param device    remote device
      * @param call      Handle of call obtained in {@link dial()} or obtained via
-     *                  {@link ACTION_CALL_CHANGED}. {@code call} may be null in which
+     *                  {@link #ACTION_CALL_CHANGED}. {@code call} may be null in which
      *                  case we will hangup all active calls.
      * @return          <code>true</code> if command has been issued successfully;
      *                   <code>false</code> otherwise;
@@ -815,15 +816,15 @@
      */
     public boolean terminateCall(BluetoothDevice device, BluetoothHeadsetClientCall call) {
         if (DBG) log("terminateCall()");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.terminateCall(device, call);
+                return service.terminateCall(device, call);
             } catch (RemoteException e) {
                 Log.e(TAG,  Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -845,15 +846,15 @@
      */
     public boolean enterPrivateMode(BluetoothDevice device, int index) {
         if (DBG) log("enterPrivateMode()");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.enterPrivateMode(device, index);
+                return service.enterPrivateMode(device, index);
             } catch (RemoteException e) {
                 Log.e(TAG,  Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -874,15 +875,15 @@
      */
     public boolean explicitCallTransfer(BluetoothDevice device) {
         if (DBG) log("explicitCallTransfer()");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.explicitCallTransfer(device);
+                return service.explicitCallTransfer(device);
             } catch (RemoteException e) {
                 Log.e(TAG,  Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -900,15 +901,15 @@
      */
     public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) {
         if (DBG) log("dial()");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.dial(device, number);
+                return service.dial(device, number);
             } catch (RemoteException e) {
                 Log.e(TAG,  Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return null;
     }
 
@@ -925,15 +926,15 @@
      */
     public boolean sendDTMF(BluetoothDevice device, byte code) {
         if (DBG) log("sendDTMF()");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.sendDTMF(device, code);
+                return service.sendDTMF(device, code);
             } catch (RemoteException e) {
                 Log.e(TAG,  Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -952,15 +953,15 @@
      */
     public boolean getLastVoiceTagNumber(BluetoothDevice device) {
         if (DBG) log("getLastVoiceTagNumber()");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getLastVoiceTagNumber(device);
+                return service.getLastVoiceTagNumber(device);
             } catch (RemoteException e) {
                 Log.e(TAG,  Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -971,10 +972,13 @@
      */
     public int getAudioState(BluetoothDevice device) {
         if (VDBG) log("getAudioState");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getAudioState(device);
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+                return service.getAudioState(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
         } else {
             Log.w(TAG, "Proxy not attached to service");
             if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
@@ -991,10 +995,13 @@
      */
     public void setAudioRouteAllowed(BluetoothDevice device, boolean allowed) {
         if (VDBG) log("setAudioRouteAllowed");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                mService.setAudioRouteAllowed(device, allowed);
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+                service.setAudioRouteAllowed(device, allowed);
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
         } else {
             Log.w(TAG, "Proxy not attached to service");
             if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
@@ -1009,10 +1016,13 @@
      */
     public boolean getAudioRouteAllowed(BluetoothDevice device) {
         if (VDBG) log("getAudioRouteAllowed");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getAudioRouteAllowed(device);
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+                return service.getAudioRouteAllowed(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
         } else {
             Log.w(TAG, "Proxy not attached to service");
             if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
@@ -1032,9 +1042,10 @@
      *                   intent;
      */
     public boolean connectAudio(BluetoothDevice device) {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.connectAudio(device);
+                return service.connectAudio(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -1057,9 +1068,10 @@
      *                   intent;
      */
     public boolean disconnectAudio(BluetoothDevice device) {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.disconnectAudio(device);
+                return service.disconnectAudio(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -1078,9 +1090,10 @@
      *                  AG not connected
      */
     public Bundle getCurrentAgFeatures(BluetoothDevice device) {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getCurrentAgFeatures(device);
+                return service.getCurrentAgFeatures(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -1092,7 +1105,7 @@
     }
 
 
-    private ServiceConnection mConnection = new ServiceConnection() {
+    private final ServiceConnection mConnection = new ServiceConnection() {
         @Override
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "Proxy object connected");
@@ -1114,15 +1127,11 @@
     };
 
     private boolean isEnabled() {
-       if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
-       return false;
+        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
     }
 
-    private boolean isValidDevice(BluetoothDevice device) {
-       if (device == null) return false;
-
-       if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-       return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
     private static void log(String msg) {
diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java
index 8d77888..07be63f 100644
--- a/core/java/android/bluetooth/BluetoothHealth.java
+++ b/core/java/android/bluetooth/BluetoothHealth.java
@@ -178,9 +178,10 @@
         BluetoothHealthAppConfiguration config =
                 new BluetoothHealthAppConfiguration(name, dataType, role, channelType);
 
-        if (mService != null) {
+        final IBluetoothHealth service = mService;
+        if (service != null) {
             try {
-                result = mService.registerAppConfiguration(config, wrapper);
+                result = service.registerAppConfiguration(config, wrapper);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -202,9 +203,10 @@
      */
     public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
         boolean result = false;
-        if (mService != null && isEnabled() && config != null) {
+        final IBluetoothHealth service = mService;
+        if (service != null && isEnabled() && config != null) {
             try {
-                result = mService.unregisterAppConfiguration(config);
+                result = service.unregisterAppConfiguration(config);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -230,10 +232,10 @@
      */
     public boolean connectChannelToSource(BluetoothDevice device,
             BluetoothHealthAppConfiguration config) {
-        if (mService != null && isEnabled() && isValidDevice(device) &&
-                config != null) {
+        final IBluetoothHealth service = mService;
+        if (service != null && isEnabled() && isValidDevice(device) && config != null) {
             try {
-                return mService.connectChannelToSource(device, config);
+                return service.connectChannelToSource(device, config);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -259,10 +261,10 @@
      */
     public boolean connectChannelToSink(BluetoothDevice device,
             BluetoothHealthAppConfiguration config, int channelType) {
-        if (mService != null && isEnabled() && isValidDevice(device) &&
-                config != null) {
+        final IBluetoothHealth service = mService;
+        if (service != null && isEnabled() && isValidDevice(device) && config != null) {
             try {
-                return mService.connectChannelToSink(device, config, channelType);
+                return service.connectChannelToSink(device, config, channelType);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -288,10 +290,10 @@
      */
     public boolean disconnectChannel(BluetoothDevice device,
             BluetoothHealthAppConfiguration config, int channelId) {
-        if (mService != null && isEnabled() && isValidDevice(device) &&
-                config != null) {
+        final IBluetoothHealth service = mService;
+        if (service != null && isEnabled() && isValidDevice(device) && config != null) {
             try {
-                return mService.disconnectChannel(device, config, channelId);
+                return service.disconnectChannel(device, config, channelId);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -317,10 +319,10 @@
      */
     public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
             BluetoothHealthAppConfiguration config) {
-        if (mService != null && isEnabled() && isValidDevice(device) &&
-                config != null) {
+        final IBluetoothHealth service = mService;
+        if (service != null && isEnabled() && isValidDevice(device) && config != null) {
             try {
-                return mService.getMainChannelFd(device, config);
+                return service.getMainChannelFd(device, config);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -348,9 +350,10 @@
      */
     @Override
     public int getConnectionState(BluetoothDevice device) {
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHealth service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getHealthDeviceConnectionState(device);
+                return service.getHealthDeviceConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -376,15 +379,16 @@
      */
     @Override
     public List<BluetoothDevice> getConnectedDevices() {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHealth service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getConnectedHealthDevices();
+                return service.getConnectedHealthDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -408,15 +412,16 @@
      */
     @Override
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHealth service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getHealthDevicesMatchingConnectionStates(states);
+                return service.getHealthDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -462,7 +467,7 @@
 
     private Context mContext;
     private ServiceListener mServiceListener;
-    private IBluetoothHealth mService;
+    private volatile IBluetoothHealth mService;
     BluetoothAdapter mAdapter;
 
     /**
@@ -546,11 +551,8 @@
         return false;
     }
 
-    private boolean isValidDevice(BluetoothDevice device) {
-        if (device == null) return false;
-
-        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-        return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
     private boolean checkAppParam(String name, int role, int channelType,
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
index a5a0243..07966ed 100644
--- a/core/java/android/bluetooth/BluetoothInputDevice.java
+++ b/core/java/android/bluetooth/BluetoothInputDevice.java
@@ -214,7 +214,7 @@
     private Context mContext;
     private ServiceListener mServiceListener;
     private BluetoothAdapter mAdapter;
-    private IBluetoothInputDevice mService;
+    private volatile IBluetoothInputDevice mService;
 
     final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
             new IBluetoothStateChangeCallback.Stub() {
@@ -325,15 +325,16 @@
      */
     public boolean connect(BluetoothDevice device) {
         if (DBG) log("connect(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.connect(device);
+                return service.connect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -365,15 +366,16 @@
      */
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.disconnect(device);
+                return service.disconnect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -382,15 +384,16 @@
      */
     public List<BluetoothDevice> getConnectedDevices() {
         if (VDBG) log("getConnectedDevices()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -399,15 +402,16 @@
      */
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         if (VDBG) log("getDevicesMatchingStates()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -416,15 +420,16 @@
      */
     public int getConnectionState(BluetoothDevice device) {
         if (VDBG) log("getState(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
@@ -445,19 +450,20 @@
      */
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
-            if (priority != BluetoothProfile.PRIORITY_OFF &&
-                priority != BluetoothProfile.PRIORITY_ON) {
-              return false;
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
+            if (priority != BluetoothProfile.PRIORITY_OFF
+                    && priority != BluetoothProfile.PRIORITY_ON) {
+                return false;
             }
             try {
-                return mService.setPriority(device, priority);
+                return service.setPriority(device, priority);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -476,15 +482,16 @@
      */
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getPriority(device);
+                return service.getPriority(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.PRIORITY_OFF;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.PRIORITY_OFF;
     }
 
@@ -507,18 +514,13 @@
     };
 
     private boolean isEnabled() {
-       if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
-       return false;
+        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
     }
 
-    private boolean isValidDevice(BluetoothDevice device) {
-       if (device == null) return false;
-
-       if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-       return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
-
     /**
      * Initiate virtual unplug for a HID input device.
      *
@@ -531,16 +533,17 @@
      */
     public boolean virtualUnplug(BluetoothDevice device) {
         if (DBG) log("virtualUnplug(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.virtualUnplug(device);
+                return service.virtualUnplug(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
 
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
 
     }
@@ -557,16 +560,17 @@
     */
     public boolean getProtocolMode(BluetoothDevice device) {
         if (VDBG) log("getProtocolMode(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getProtocolMode(device);
+                return service.getProtocolMode(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
-            return false;
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
+        return false;
     }
 
     /**
@@ -581,15 +585,16 @@
      */
     public boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
         if (DBG) log("setProtocolMode(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.setProtocolMode(device, protocolMode);
+                return service.setProtocolMode(device, protocolMode);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -606,17 +611,22 @@
      *               true otherwise
      * @hide
      */
-    public boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) {
-        if (VDBG) log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId + "bufferSize=" + bufferSize);
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+    public boolean getReport(BluetoothDevice device, byte reportType, byte reportId,
+            int bufferSize) {
+        if (VDBG) {
+            log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId
+                    + "bufferSize=" + bufferSize);
+        }
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getReport(device, reportType, reportId, bufferSize);
+                return service.getReport(device, reportType, reportId, bufferSize);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -634,15 +644,16 @@
      */
     public boolean setReport(BluetoothDevice device, byte reportType, String report) {
         if (VDBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.setReport(device, reportType, report);
+                return service.setReport(device, reportType, report);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -659,15 +670,16 @@
      */
     public boolean sendData(BluetoothDevice device, String report) {
         if (DBG) log("sendData(" + device + "), report=" + report);
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.sendData(device, report);
+                return service.sendData(device, report);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -683,15 +695,16 @@
      */
     public boolean getIdleTime(BluetoothDevice device) {
         if (DBG) log("getIdletime(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getIdleTime(device);
+                return service.getIdleTime(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -708,15 +721,16 @@
      */
     public boolean setIdleTime(BluetoothDevice device, byte idleTime) {
         if (DBG) log("setIdletime(" + device + "), idleTime=" + idleTime);
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.setIdleTime(device, idleTime);
+                return service.setIdleTime(device, idleTime);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
diff --git a/core/java/android/bluetooth/BluetoothInputHost.java b/core/java/android/bluetooth/BluetoothInputHost.java
index 68d105f..6a0506d 100644
--- a/core/java/android/bluetooth/BluetoothInputHost.java
+++ b/core/java/android/bluetooth/BluetoothInputHost.java
@@ -26,8 +26,8 @@
 import android.os.RemoteException;
 import android.util.Log;
 
-import java.util.Arrays;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -114,7 +114,7 @@
 
     private ServiceListener mServiceListener;
 
-    private IBluetoothInputHost mService;
+    private volatile IBluetoothInputHost mService;
 
     private BluetoothAdapter mAdapter;
 
@@ -195,24 +195,18 @@
         }
     };
 
-    private ServiceConnection mConnection = new ServiceConnection() {
-
+    private final ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             Log.d(TAG, "onServiceConnected()");
-
             mService = IBluetoothInputHost.Stub.asInterface(service);
-
             if (mServiceListener != null) {
                 mServiceListener.onServiceConnected(BluetoothProfile.INPUT_HOST,
                     BluetoothInputHost.this);
             }
         }
-
         public void onServiceDisconnected(ComponentName className) {
             Log.d(TAG, "onServiceDisconnected()");
-
             mService = null;
-
             if (mServiceListener != null) {
                 mServiceListener.onServiceDisconnected(BluetoothProfile.INPUT_HOST);
             }
@@ -283,9 +277,10 @@
     public List<BluetoothDevice> getConnectedDevices() {
         Log.v(TAG, "getConnectedDevices()");
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
-                return mService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -302,9 +297,10 @@
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         Log.v(TAG, "getDevicesMatchingConnectionStates(): states=" + Arrays.toString(states));
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
-                return mService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -321,9 +317,10 @@
     public int getConnectionState(BluetoothDevice device) {
         Log.v(TAG, "getConnectionState(): device=" + device);
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
-                return mService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -363,13 +360,14 @@
             return false;
         }
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
                 BluetoothHidDeviceAppConfiguration config =
-                    new BluetoothHidDeviceAppConfiguration();
+                        new BluetoothHidDeviceAppConfiguration();
                 BluetoothHidDeviceCallbackWrapper cbw =
-                    new BluetoothHidDeviceCallbackWrapper(callback);
-                result = mService.registerApp(config, sdp, inQos, outQos, cbw);
+                        new BluetoothHidDeviceCallbackWrapper(callback);
+                result = service.registerApp(config, sdp, inQos, outQos, cbw);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -397,9 +395,10 @@
 
         boolean result = false;
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
-                result = mService.unregisterApp(config);
+                result = service.unregisterApp(config);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -421,9 +420,10 @@
     public boolean sendReport(BluetoothDevice device, int id, byte[] data) {
         boolean result = false;
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
-                result = mService.sendReport(device, id, data);
+                result = service.sendReport(device, id, data);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -448,9 +448,10 @@
 
         boolean result = false;
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
-                result = mService.replyReport(device, type, id, data);
+                result = service.replyReport(device, type, id, data);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -473,9 +474,10 @@
 
         boolean result = false;
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
-                result = mService.reportError(device, error);
+                result = service.reportError(device, error);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -496,9 +498,10 @@
 
         boolean result = false;
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
-                result = mService.unplug(device);
+                result = service.unplug(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -520,9 +523,10 @@
 
         boolean result = false;
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
-                result = mService.connect(device);
+                result = service.connect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -543,9 +547,10 @@
 
         boolean result = false;
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
-                result = mService.disconnect(device);
+                result = service.disconnect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java
index 2e73051..0f801fd 100644
--- a/core/java/android/bluetooth/BluetoothMap.java
+++ b/core/java/android/bluetooth/BluetoothMap.java
@@ -16,15 +16,18 @@
 
 package android.bluetooth;
 
-import java.util.List;
-import java.util.ArrayList;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.os.*;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
 import android.util.Log;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * This class provides the APIs to control the Bluetooth MAP
  * Profile.
@@ -39,7 +42,7 @@
     public static final String ACTION_CONNECTION_STATE_CHANGED =
         "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED";
 
-    private IBluetoothMap mService;
+    private volatile IBluetoothMap mService;
     private final Context mContext;
     private ServiceListener mServiceListener;
     private BluetoothAdapter mAdapter;
@@ -156,10 +159,13 @@
      */
     public int getState() {
         if (VDBG) log("getState()");
-        if (mService != null) {
+        final IBluetoothMap service = mService;
+        if (service != null) {
             try {
-                return mService.getState();
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+                return service.getState();
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
         } else {
             Log.w(TAG, "Proxy not attached to service");
             if (DBG) log(Log.getStackTraceString(new Throwable()));
@@ -175,10 +181,13 @@
      */
     public BluetoothDevice getClient() {
         if (VDBG) log("getClient()");
-        if (mService != null) {
+        final IBluetoothMap service = mService;
+        if (service != null) {
             try {
-                return mService.getClient();
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+                return service.getClient();
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
         } else {
             Log.w(TAG, "Proxy not attached to service");
             if (DBG) log(Log.getStackTraceString(new Throwable()));
@@ -193,10 +202,13 @@
      */
     public boolean isConnected(BluetoothDevice device) {
         if (VDBG) log("isConnected(" + device + ")");
-        if (mService != null) {
+        final IBluetoothMap service = mService;
+        if (service != null) {
             try {
-                return mService.isConnected(device);
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+                return service.isConnected(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
         } else {
             Log.w(TAG, "Proxy not attached to service");
             if (DBG) log(Log.getStackTraceString(new Throwable()));
@@ -222,16 +234,16 @@
      */
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
+        final IBluetoothMap service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.disconnect(device);
+                return service.disconnect(device);
             } catch (RemoteException e) {
               Log.e(TAG, Log.getStackTraceString(new Throwable()));
               return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -262,15 +274,16 @@
      */
     public List<BluetoothDevice> getConnectedDevices() {
         if (DBG) log("getConnectedDevices()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothMap service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -281,15 +294,16 @@
      */
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         if (DBG) log("getDevicesMatchingStates()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothMap service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -300,16 +314,16 @@
      */
     public int getConnectionState(BluetoothDevice device) {
         if (DBG) log("getConnectionState(" + device + ")");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
+        final IBluetoothMap service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
@@ -326,20 +340,20 @@
      */
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
-            if (priority != BluetoothProfile.PRIORITY_OFF &&
-                priority != BluetoothProfile.PRIORITY_ON) {
-              return false;
+        final IBluetoothMap service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
+            if (priority != BluetoothProfile.PRIORITY_OFF
+                    && priority != BluetoothProfile.PRIORITY_ON) {
+                return false;
             }
             try {
-                return mService.setPriority(device, priority);
+                return service.setPriority(device, priority);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -355,16 +369,16 @@
      */
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
+        final IBluetoothMap service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getPriority(device);
+                return service.getPriority(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return PRIORITY_OFF;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return PRIORITY_OFF;
     }
 
@@ -395,12 +409,8 @@
         log("Bluetooth is Not enabled");
         return false;
     }
-    private boolean isValidDevice(BluetoothDevice device) {
-       if (device == null) return false;
-
-       if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-       return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
-
 }
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
index ccab3cd..b8fadf4 100644
--- a/core/java/android/bluetooth/BluetoothMapClient.java
+++ b/core/java/android/bluetooth/BluetoothMapClient.java
@@ -59,7 +59,7 @@
     public static final String EXTRA_SENDER_CONTACT_NAME =
             "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_NAME";
 
-    private IBluetoothMapClient mService;
+    private volatile IBluetoothMapClient mService;
     private final Context mContext;
     private ServiceListener mServiceListener;
     private BluetoothAdapter mAdapter;
@@ -176,9 +176,10 @@
      */
     public boolean isConnected(BluetoothDevice device) {
         if (VDBG) Log.d(TAG, "isConnected(" + device + ")");
-        if (mService != null) {
+        final IBluetoothMapClient service = mService;
+        if (service != null) {
             try {
-                return mService.isConnected(device);
+                return service.isConnected(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -195,9 +196,10 @@
      */
     public boolean connect(BluetoothDevice device) {
         if (DBG) Log.d(TAG, "connect(" + device + ")" + "for MAPS MCE");
-        if (mService != null) {
+        final IBluetoothMapClient service = mService;
+        if (service != null) {
             try {
-                return mService.connect(device);
+                return service.connect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -216,15 +218,15 @@
      */
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) Log.d(TAG, "disconnect(" + device + ")");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothMapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.disconnect(device);
+                return service.disconnect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -236,15 +238,16 @@
     @Override
     public List<BluetoothDevice> getConnectedDevices() {
         if (DBG) Log.d(TAG, "getConnectedDevices()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothMapClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<>();
     }
 
@@ -256,15 +259,16 @@
     @Override
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         if (DBG) Log.d(TAG, "getDevicesMatchingStates()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothMapClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<>();
     }
 
@@ -276,16 +280,16 @@
     @Override
     public int getConnectionState(BluetoothDevice device) {
         if (DBG) Log.d(TAG, "getConnectionState(" + device + ")");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothMapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
@@ -300,20 +304,20 @@
      */
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) Log.d(TAG, "setPriority(" + device + ", " + priority + ")");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
-            if (priority != BluetoothProfile.PRIORITY_OFF &&
-                    priority != BluetoothProfile.PRIORITY_ON) {
+        final IBluetoothMapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
+            if (priority != BluetoothProfile.PRIORITY_OFF
+                    && priority != BluetoothProfile.PRIORITY_ON) {
                 return false;
             }
             try {
-                return mService.setPriority(device, priority);
+                return service.setPriority(device, priority);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -329,16 +333,16 @@
      */
     public int getPriority(BluetoothDevice device) {
         if (VDBG) Log.d(TAG, "getPriority(" + device + ")");
-        if (mService != null && isEnabled() &&
-                isValidDevice(device)) {
+        final IBluetoothMapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getPriority(device);
+                return service.getPriority(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return PRIORITY_OFF;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return PRIORITY_OFF;
     }
 
@@ -357,9 +361,10 @@
     public boolean sendMessage(BluetoothDevice device, Uri[] contacts, String message,
             PendingIntent sentIntent, PendingIntent deliveredIntent) {
         if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message);
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothMapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.sendMessage(device, contacts, message, sentIntent, deliveredIntent);
+                return service.sendMessage(device, contacts, message, sentIntent, deliveredIntent);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
@@ -376,9 +381,10 @@
      */
     public boolean getUnreadMessages(BluetoothDevice device) {
         if (DBG) Log.d(TAG, "getUnreadMessages(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothMapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getUnreadMessages(device);
+                return service.getUnreadMessages(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
@@ -413,12 +419,8 @@
         return false;
     }
 
-    private boolean isValidDevice(BluetoothDevice device) {
-        if (device == null) return false;
-
-        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-        return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
-
 }
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index 2a026a9..123d10b 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -121,7 +121,7 @@
     private Context mContext;
     private ServiceListener mServiceListener;
     private BluetoothAdapter mAdapter;
-    private IBluetoothPan mPanService;
+    private volatile IBluetoothPan mPanService;
 
     /**
      * Create a BluetoothPan proxy object for interacting with the local
@@ -235,16 +235,16 @@
      */
     public boolean connect(BluetoothDevice device) {
         if (DBG) log("connect(" + device + ")");
-        if (mPanService != null && isEnabled() &&
-            isValidDevice(device)) {
+        final IBluetoothPan service = mPanService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mPanService.connect(device);
+                return service.connect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -276,16 +276,16 @@
      */
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
-        if (mPanService != null && isEnabled() &&
-            isValidDevice(device)) {
+        final IBluetoothPan service = mPanService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mPanService.disconnect(device);
+                return service.disconnect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -294,15 +294,16 @@
      */
     public List<BluetoothDevice> getConnectedDevices() {
         if (VDBG) log("getConnectedDevices()");
-        if (mPanService != null && isEnabled()) {
+        final IBluetoothPan service = mPanService;
+        if (service != null && isEnabled()) {
             try {
-                return mPanService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -311,15 +312,16 @@
      */
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         if (VDBG) log("getDevicesMatchingStates()");
-        if (mPanService != null && isEnabled()) {
+        final IBluetoothPan service = mPanService;
+        if (service != null && isEnabled()) {
             try {
-                return mPanService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -328,25 +330,25 @@
      */
     public int getConnectionState(BluetoothDevice device) {
         if (VDBG) log("getState(" + device + ")");
-        if (mPanService != null && isEnabled()
-            && isValidDevice(device)) {
+        final IBluetoothPan service = mPanService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mPanService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
     public void setBluetoothTethering(boolean value) {
         if (DBG) log("setBluetoothTethering(" + value + ")");
-
-        if (mPanService != null && isEnabled()) {
+        final IBluetoothPan service = mPanService;
+        if (service != null && isEnabled()) {
             try {
-                mPanService.setBluetoothTethering(value);
+                service.setBluetoothTethering(value);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
             }
@@ -355,10 +357,10 @@
 
     public boolean isTetheringOn() {
         if (VDBG) log("isTetheringOn()");
-
-        if (mPanService != null && isEnabled()) {
+        final IBluetoothPan service = mPanService;
+        if (service != null && isEnabled()) {
             try {
-                return mPanService.isTetheringOn();
+                return service.isTetheringOn();
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
             }
@@ -370,7 +372,6 @@
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "BluetoothPAN Proxy object connected");
             mPanService = IBluetoothPan.Stub.asInterface(Binder.allowBlocking(service));
-
             if (mServiceListener != null) {
                 mServiceListener.onServiceConnected(BluetoothProfile.PAN,
                                                     BluetoothPan.this);
@@ -386,15 +387,11 @@
     };
 
     private boolean isEnabled() {
-       if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
-       return false;
+        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
     }
 
-    private boolean isValidDevice(BluetoothDevice device) {
-       if (device == null) return false;
-
-       if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-       return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
     private static void log(String msg) {
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index dc01fc7..f16160e4 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -20,8 +20,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.os.RemoteException;
 import android.os.IBinder;
+import android.os.RemoteException;
 import android.util.Log;
 
 /**
@@ -67,7 +67,7 @@
     public static final String PBAP_STATE_CHANGED_ACTION =
         "android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED";
 
-    private IBluetoothPbap mService;
+    private volatile IBluetoothPbap mService;
     private final Context mContext;
     private ServiceListener mServiceListener;
     private BluetoothAdapter mAdapter;
@@ -212,10 +212,13 @@
      */
     public int getState() {
         if (VDBG) log("getState()");
-        if (mService != null) {
+        final IBluetoothPbap service = mService;
+        if (service != null) {
             try {
-                return mService.getState();
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+                return service.getState();
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
         } else {
             Log.w(TAG, "Proxy not attached to service");
             if (DBG) log(Log.getStackTraceString(new Throwable()));
@@ -231,10 +234,13 @@
      */
     public BluetoothDevice getClient() {
         if (VDBG) log("getClient()");
-        if (mService != null) {
+        final IBluetoothPbap service = mService;
+        if (service != null) {
             try {
-                return mService.getClient();
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+                return service.getClient();
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
         } else {
             Log.w(TAG, "Proxy not attached to service");
             if (DBG) log(Log.getStackTraceString(new Throwable()));
@@ -249,10 +255,13 @@
      */
     public boolean isConnected(BluetoothDevice device) {
         if (VDBG) log("isConnected(" + device + ")");
-        if (mService != null) {
+        final IBluetoothPbap service = mService;
+        if (service != null) {
             try {
-                return mService.isConnected(device);
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+                return service.isConnected(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
         } else {
             Log.w(TAG, "Proxy not attached to service");
             if (DBG) log(Log.getStackTraceString(new Throwable()));
@@ -267,9 +276,10 @@
      */
     public boolean disconnect() {
         if (DBG) log("disconnect()");
-        if (mService != null) {
+        final IBluetoothPbap service = mService;
+        if (service != null) {
             try {
-                mService.disconnect();
+                service.disconnect();
                 return true;
             } catch (RemoteException e) {Log.e(TAG, e.toString());}
         } else {
diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java
index 9f00e1a..28b551e 100644
--- a/core/java/android/bluetooth/BluetoothPbapClient.java
+++ b/core/java/android/bluetooth/BluetoothPbapClient.java
@@ -16,17 +16,18 @@
 
 package android.bluetooth;
 
-import java.util.List;
-import java.util.ArrayList;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.os.RemoteException;
 import android.os.Binder;
 import android.os.IBinder;
+import android.os.RemoteException;
 import android.util.Log;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * This class provides the APIs to control the Bluetooth PBAP Client Profile.
  *@hide
@@ -40,7 +41,7 @@
     public static final String ACTION_CONNECTION_STATE_CHANGED =
         "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED";
 
-    private IBluetoothPbapClient mService;
+    private volatile IBluetoothPbapClient mService;
     private final Context mContext;
     private ServiceListener mServiceListener;
     private BluetoothAdapter mAdapter;
@@ -171,15 +172,16 @@
         if (DBG) {
             log("connect(" + device + ") for PBAP Client.");
         }
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothPbapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.connect(device);
+                return service.connect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) {
+        if (service == null) {
             Log.w(TAG, "Proxy not attached to service");
         }
         return false;
@@ -196,16 +198,17 @@
         if (DBG) {
             log("disconnect(" + device + ")" + new Exception() );
         }
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothPbapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                mService.disconnect(device);
+                service.disconnect(device);
                 return true;
             } catch (RemoteException e) {
               Log.e(TAG, Log.getStackTraceString(new Throwable()));
               return false;
             }
         }
-        if (mService == null) {
+        if (service == null) {
             Log.w(TAG, "Proxy not attached to service");
         }
         return false;
@@ -222,15 +225,16 @@
         if (DBG) {
             log("getConnectedDevices()");
         }
-        if (mService != null && isEnabled()) {
+        final IBluetoothPbapClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) {
+        if (service == null) {
             Log.w(TAG, "Proxy not attached to service");
         }
         return new ArrayList<BluetoothDevice>();
@@ -246,15 +250,16 @@
         if (DBG) {
             log("getDevicesMatchingStates()");
         }
-        if (mService != null && isEnabled()) {
+        final IBluetoothPbapClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) {
+        if (service == null) {
             Log.w(TAG, "Proxy not attached to service");
         }
         return new ArrayList<BluetoothDevice>();
@@ -270,15 +275,16 @@
         if (DBG) {
             log("getConnectionState(" + device + ")");
         }
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothPbapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mService == null) {
+        if (service == null) {
             Log.w(TAG, "Proxy not attached to service");
         }
         return BluetoothProfile.STATE_DISCONNECTED;
@@ -318,14 +324,8 @@
         return false;
     }
 
-    private boolean isValidDevice(BluetoothDevice device) {
-       if (device == null) {
-           return false;
-       }
-       if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
-           return true;
-       }
-       return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
     /**
@@ -336,27 +336,27 @@
      * {@link #PRIORITY_OFF},
      *
      * @param device Paired bluetooth device
-     * @param priority
+     * @param priority Priority of this profile
      * @return true if priority is set, false on error
      */
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) {
             log("setPriority(" + device + ", " + priority + ")");
         }
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
-            if (priority != BluetoothProfile.PRIORITY_OFF &&
-                priority != BluetoothProfile.PRIORITY_ON) {
-              return false;
+        final IBluetoothPbapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
+            if (priority != BluetoothProfile.PRIORITY_OFF
+                    && priority != BluetoothProfile.PRIORITY_ON) {
+                return false;
             }
             try {
-                return mService.setPriority(device, priority);
+                return service.setPriority(device, priority);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) {
+        if (service == null) {
             Log.w(TAG, "Proxy not attached to service");
         }
         return false;
@@ -376,15 +376,16 @@
         if (VDBG) {
             log("getPriority(" + device + ")");
         }
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothPbapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getPriority(device);
+                return service.getPriority(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return PRIORITY_OFF;
             }
         }
-        if (mService == null) {
+        if (service == null) {
             Log.w(TAG, "Proxy not attached to service");
         }
         return PRIORITY_OFF;
diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java
index 89c1bf8..f9ddb2e 100644
--- a/core/java/android/bluetooth/BluetoothSap.java
+++ b/core/java/android/bluetooth/BluetoothSap.java
@@ -16,19 +16,18 @@
 
 package android.bluetooth;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.os.RemoteException;
 import android.os.Binder;
 import android.os.IBinder;
-import android.os.ServiceManager;
+import android.os.RemoteException;
 import android.util.Log;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * This class provides the APIs to control the Bluetooth SIM
  * Access Profile (SAP).
@@ -67,7 +66,7 @@
     public static final String ACTION_CONNECTION_STATE_CHANGED =
         "android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED";
 
-    private IBluetoothSap mService;
+    private volatile IBluetoothSap mService;
     private final Context mContext;
     private ServiceListener mServiceListener;
     private BluetoothAdapter mAdapter;
@@ -196,10 +195,13 @@
      */
     public int getState() {
         if (VDBG) log("getState()");
-        if (mService != null) {
+        final IBluetoothSap service = mService;
+        if (service != null) {
             try {
-                return mService.getState();
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+                return service.getState();
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
         } else {
             Log.w(TAG, "Proxy not attached to service");
             if (DBG) log(Log.getStackTraceString(new Throwable()));
@@ -216,10 +218,13 @@
      */
     public BluetoothDevice getClient() {
         if (VDBG) log("getClient()");
-        if (mService != null) {
+        final IBluetoothSap service = mService;
+        if (service != null) {
             try {
-                return mService.getClient();
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+                return service.getClient();
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
         } else {
             Log.w(TAG, "Proxy not attached to service");
             if (DBG) log(Log.getStackTraceString(new Throwable()));
@@ -235,10 +240,13 @@
      */
     public boolean isConnected(BluetoothDevice device) {
         if (VDBG) log("isConnected(" + device + ")");
-        if (mService != null) {
+        final IBluetoothSap service = mService;
+        if (service != null) {
             try {
-                return mService.isConnected(device);
-            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+                return service.isConnected(device);
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
         } else {
             Log.w(TAG, "Proxy not attached to service");
             if (DBG) log(Log.getStackTraceString(new Throwable()));
@@ -266,16 +274,16 @@
      */
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
+        final IBluetoothSap service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.disconnect(device);
+                return service.disconnect(device);
             } catch (RemoteException e) {
               Log.e(TAG, Log.getStackTraceString(new Throwable()));
               return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -287,15 +295,16 @@
      */
     public List<BluetoothDevice> getConnectedDevices() {
         if (DBG) log("getConnectedDevices()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothSap service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -307,15 +316,16 @@
      */
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         if (DBG) log("getDevicesMatchingStates()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothSap service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -327,16 +337,16 @@
      */
     public int getConnectionState(BluetoothDevice device) {
         if (DBG) log("getConnectionState(" + device + ")");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
+        final IBluetoothSap service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
@@ -352,20 +362,20 @@
      */
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
-            if (priority != BluetoothProfile.PRIORITY_OFF &&
-                priority != BluetoothProfile.PRIORITY_ON) {
-              return false;
+        final IBluetoothSap service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
+            if (priority != BluetoothProfile.PRIORITY_OFF
+                    && priority != BluetoothProfile.PRIORITY_ON) {
+                return false;
             }
             try {
-                return mService.setPriority(device, priority);
+                return service.setPriority(device, priority);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -378,20 +388,20 @@
      */
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
-        if (mService != null && isEnabled() &&
-            isValidDevice(device)) {
+        final IBluetoothSap service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getPriority(device);
+                return service.getPriority(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return PRIORITY_OFF;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return PRIORITY_OFF;
     }
 
-    private ServiceConnection mConnection = new ServiceConnection() {
+    private final ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) log("Proxy object connected");
             mService = IBluetoothSap.Stub.asInterface(Binder.allowBlocking(service));
@@ -421,13 +431,8 @@
         return false;
     }
 
-    private boolean isValidDevice(BluetoothDevice device) {
-       if (device == null)
-           return false;
-
-       if (BluetoothAdapter.checkBluetoothAddress(device.getAddress()))
-           return true;
-       return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
 }
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index 9e9c8fe..7106a84 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -137,6 +137,11 @@
      * the PendingIntent. Use this method of scanning if your process is not always running and it
      * should be started when scan results are available.
      * <p>
+     * An app must hold
+     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
+     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
+     * in order to get results.
+     * <p>
      * When the PendingIntent is delivered, the Intent passed to the receiver or activity
      * will contain one or more of the extras {@link #EXTRA_CALLBACK_TYPE},
      * {@link #EXTRA_ERROR_CODE} and {@link #EXTRA_LIST_SCAN_RESULT} to indicate the result of
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index ad7a5ab..664bcbca 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -718,6 +718,10 @@
      * Cycles do not exist because they are illegal and screened for during installation.
      *
      * May be null if no splits are installed, or if no dependencies exist between them.
+     *
+     * NOTE: Any change to the way split dependencies are stored must update the logic that
+     *       creates the class loader context for dexopt (DexoptUtils#getClassLoaderContexts).
+     *
      * @hide
      */
     public SparseArray<int[]> splitDependencies;
diff --git a/core/java/android/database/sqlite/SQLiteGlobal.java b/core/java/android/database/sqlite/SQLiteGlobal.java
index 571656a..94d5555 100644
--- a/core/java/android/database/sqlite/SQLiteGlobal.java
+++ b/core/java/android/database/sqlite/SQLiteGlobal.java
@@ -16,6 +16,7 @@
 
 package android.database.sqlite;
 
+import android.annotation.TestApi;
 import android.content.res.Resources;
 import android.os.StatFs;
 import android.os.SystemProperties;
@@ -34,6 +35,7 @@
  *
  * @hide
  */
+@TestApi
 public final class SQLiteGlobal {
     private static final String TAG = "SQLiteGlobal";
 
diff --git a/core/java/android/hardware/camera2/DngCreator.java b/core/java/android/hardware/camera2/DngCreator.java
index 1a51acd..cc484ea 100644
--- a/core/java/android/hardware/camera2/DngCreator.java
+++ b/core/java/android/hardware/camera2/DngCreator.java
@@ -18,7 +18,6 @@
 
 import android.annotation.IntRange;
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.graphics.ImageFormat;
@@ -37,6 +36,7 @@
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
+import java.util.Locale;
 import java.util.TimeZone;
 
 /**
@@ -122,7 +122,7 @@
         // Create this fresh each time since the time zone may change while a long-running application
         // is active.
         final DateFormat dateTimeStampFormat =
-            new SimpleDateFormat(TIFF_DATETIME_FORMAT);
+                new SimpleDateFormat(TIFF_DATETIME_FORMAT, Locale.US);
         dateTimeStampFormat.setTimeZone(TimeZone.getDefault());
 
         // Format for metadata
@@ -472,7 +472,8 @@
 
     private static final String GPS_DATE_FORMAT_STR = "yyyy:MM:dd";
     private static final String TIFF_DATETIME_FORMAT = "yyyy:MM:dd HH:mm:ss";
-    private static final DateFormat sExifGPSDateStamp = new SimpleDateFormat(GPS_DATE_FORMAT_STR);
+    private static final DateFormat sExifGPSDateStamp =
+            new SimpleDateFormat(GPS_DATE_FORMAT_STR, Locale.US);
     private final Calendar mGPSTimeStampCalendar = Calendar
             .getInstance(TimeZone.getTimeZone("UTC"));
 
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 0d5c5e3..bfeb14d 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -1769,7 +1769,7 @@
         }
 
         @Override
-        public void onRepeatingRequestError(long lastFrameNumber) {
+        public void onRepeatingRequestError(long lastFrameNumber, int repeatingRequestId) {
             if (DEBUG) {
                 Log.d(TAG, "Repeating request error received. Last frame number is " +
                         lastFrameNumber);
@@ -1782,7 +1782,10 @@
                 }
 
                 checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber);
-                mRepeatingRequestId = REQUEST_ID_NONE;
+                // Check if there is already a new repeating request
+                if (mRepeatingRequestId == repeatingRequestId) {
+                    mRepeatingRequestId = REQUEST_ID_NONE;
+                }
             }
         }
 
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceState.java b/core/java/android/hardware/camera2/legacy/CameraDeviceState.java
index 135d92b..89ecd5f 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceState.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceState.java
@@ -77,7 +77,7 @@
         void onCaptureStarted(RequestHolder holder, long timestamp);
         void onCaptureResult(CameraMetadataNative result, RequestHolder holder);
         void onRequestQueueEmpty();
-        void onRepeatingRequestError(long lastFrameNumber);
+        void onRepeatingRequestError(long lastFrameNumber, int repeatingRequestId);
     }
 
     /**
@@ -208,12 +208,14 @@
      * <p>Repeating request has been stopped due to an error such as abandoned output surfaces.</p>
      *
      * @param lastFrameNumber Frame number of the last repeating request before it is stopped.
+     * @param repeatingRequestId The ID of the repeating request being stopped
      */
-    public synchronized void setRepeatingRequestError(final long lastFrameNumber) {
+    public synchronized void setRepeatingRequestError(final long lastFrameNumber,
+            final int repeatingRequestId) {
         mCurrentHandler.post(new Runnable() {
             @Override
             public void run() {
-                mCurrentListener.onRepeatingRequestError(lastFrameNumber);
+                mCurrentListener.onRepeatingRequestError(lastFrameNumber, repeatingRequestId);
             }
         });
     }
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index d8df9a0..49d4096 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -264,10 +264,10 @@
         }
 
         @Override
-        public void onRepeatingRequestError(long lastFrameNumber) {
+        public void onRepeatingRequestError(long lastFrameNumber, int repeatingRequestId) {
+            Object[] objArray = new Object[] { lastFrameNumber, repeatingRequestId };
             Message msg = getHandler().obtainMessage(REPEATING_REQUEST_ERROR,
-                    /*arg1*/ (int) (lastFrameNumber & 0xFFFFFFFFL),
-                    /*arg2*/ (int) ( (lastFrameNumber >> 32) & 0xFFFFFFFFL));
+                    /*obj*/ objArray);
             getHandler().sendMessage(msg);
         }
 
@@ -329,9 +329,10 @@
                             break;
                         }
                         case REPEATING_REQUEST_ERROR: {
-                            long lastFrameNumber = msg.arg2 & 0xFFFFFFFFL;
-                            lastFrameNumber = (lastFrameNumber << 32) | (msg.arg1 & 0xFFFFFFFFL);
-                            mCallbacks.onRepeatingRequestError(lastFrameNumber);
+                            Object[] objArray = (Object[]) msg.obj;
+                            long lastFrameNumber = (Long) objArray[0];
+                            int repeatingRequestId = (Integer) objArray[1];
+                            mCallbacks.onRepeatingRequestError(lastFrameNumber, repeatingRequestId);
                             break;
                         }
                         case REQUEST_QUEUE_EMPTY: {
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index 621ea84..cb59fd1 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -263,7 +263,8 @@
         }
 
         @Override
-        public void onRepeatingRequestError(final long lastFrameNumber) {
+        public void onRepeatingRequestError(final long lastFrameNumber,
+                final int repeatingRequestId) {
             mResultHandler.post(new Runnable() {
                 @Override
                 public void run() {
@@ -271,7 +272,8 @@
                         Log.d(TAG, "doing onRepeatingRequestError callback.");
                     }
                     try {
-                        mDeviceCallbacks.onRepeatingRequestError(lastFrameNumber);
+                        mDeviceCallbacks.onRepeatingRequestError(lastFrameNumber,
+                                repeatingRequestId);
                     } catch (RemoteException e) {
                         throw new IllegalStateException(
                                 "Received remote exception during onRepeatingRequestError " +
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index 565a43e..aaf07e6 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -939,7 +939,8 @@
                             Log.d(TAG, "Stopped repeating request. Last frame number is " +
                                     lastFrameNumber);
                         }
-                        mDeviceState.setRepeatingRequestError(lastFrameNumber);
+                        mDeviceState.setRepeatingRequestError(lastFrameNumber,
+                                burstHolder.getRequestId());
                     }
 
                     if (DEBUG) {
diff --git a/core/java/android/hardware/location/NanoAppInstanceInfo.java b/core/java/android/hardware/location/NanoAppInstanceInfo.java
index ac6d83f..2623830 100644
--- a/core/java/android/hardware/location/NanoAppInstanceInfo.java
+++ b/core/java/android/hardware/location/NanoAppInstanceInfo.java
@@ -287,8 +287,10 @@
         mPublisher = in.readString();
         mName = in.readString();
 
+        mHandle = in.readInt();
         mAppId = in.readLong();
         mAppVersion = in.readInt();
+        mContexthubId = in.readInt();
         mNeededReadMemBytes = in.readInt();
         mNeededWriteMemBytes = in.readInt();
         mNeededExecMemBytes = in.readInt();
@@ -309,6 +311,8 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeString(mPublisher);
         out.writeString(mName);
+
+        out.writeInt(mHandle);
         out.writeLong(mAppId);
         out.writeInt(mAppVersion);
         out.writeInt(mContexthubId);
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 1bb0fbb..f527f77 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -18,14 +18,13 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.net.ProxyInfo;
-import android.os.Parcelable;
 import android.os.Parcel;
+import android.os.Parcelable;
 import android.text.TextUtils;
 
-import java.net.InetAddress;
 import java.net.Inet4Address;
 import java.net.Inet6Address;
+import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -504,11 +503,22 @@
     }
 
     /**
+     * Make sure this LinkProperties instance contains routes that cover the local subnet
+     * of its link addresses. Add any route that is missing.
+     * @hide
+     */
+    public void ensureDirectlyConnectedRoutes() {
+        for (LinkAddress addr: mLinkAddresses) {
+            addRoute(new RouteInfo(addr, null, mIfaceName));
+        }
+    }
+
+    /**
      * Returns all the routes on this link and all the links stacked above it.
      * @hide
      */
     public List<RouteInfo> getAllRoutes() {
-        List<RouteInfo> routes = new ArrayList();
+        List<RouteInfo> routes = new ArrayList<>();
         routes.addAll(mRoutes);
         for (LinkProperties stacked: mStackedLinks.values()) {
             routes.addAll(stacked.getAllRoutes());
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index cea5715..66b6b47 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -53,6 +53,8 @@
     private static final String TAG = "BatteryStats";
 
     private static final boolean LOCAL_LOGV = false;
+    /** Fetching RPM stats is too slow to do each time screen changes, so disable it. */
+    protected static final boolean SCREEN_OFF_RPM_STATS_ENABLED = false;
 
     /** @hide */
     public static final String SERVICE_NAME = "batterystats";
@@ -213,8 +215,10 @@
      *   - Fixed bugs in background timers and BLE scan time
      * New in version 25:
      *   - Package wakeup alarms are now on screen-off timebase
+     * New in version 26:
+     *   - Resource power manager (rpm) states [but screenOffRpm is disabled from working properly]
      */
-    static final String CHECKIN_VERSION = "25";
+    static final String CHECKIN_VERSION = "26";
 
     /**
      * Old version, we hit 9 and ran out of room, need to remove.
@@ -233,6 +237,10 @@
     private static final String CPU_DATA = "cpu";
     private static final String GLOBAL_CPU_FREQ_DATA = "gcf";
     private static final String CPU_TIMES_AT_FREQ_DATA = "ctf";
+    // rpm line is:
+    // BATTERY_STATS_CHECKIN_VERSION, uid, which, "rpm", state/voter name, total time, total count,
+    // screen-off time, screen-off count
+    private static final String RESOURCE_POWER_MANAGER_DATA = "rpm";
     private static final String SENSOR_DATA = "sr";
     private static final String VIBRATOR_DATA = "vib";
     private static final String FOREGROUND_ACTIVITY_DATA = "fg";
@@ -2648,6 +2656,16 @@
 
     public abstract Map<String, ? extends Timer> getKernelWakelockStats();
 
+    /**
+     * Returns Timers tracking the total time of each Resource Power Manager state and voter.
+     */
+    public abstract Map<String, ? extends Timer> getRpmStats();
+    /**
+     * Returns Timers tracking the screen-off time of each Resource Power Manager state and voter.
+     */
+    public abstract Map<String, ? extends Timer> getScreenOffRpmStats();
+
+
     public abstract LongSparseArray<? extends Timer> getKernelMemoryStats();
 
     public abstract void writeToParcelWithoutUids(Parcel out, int flags);
@@ -3309,6 +3327,30 @@
             }
         }
 
+        final Map<String, ? extends Timer> rpmStats = getRpmStats();
+        final Map<String, ? extends Timer> screenOffRpmStats = getScreenOffRpmStats();
+        if (rpmStats.size() > 0) {
+            for (Map.Entry<String, ? extends Timer> ent : rpmStats.entrySet()) {
+                sb.setLength(0);
+                Timer totalTimer = ent.getValue();
+                long timeMs = (totalTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+                int count = totalTimer.getCountLocked(which);
+                Timer screenOffTimer = screenOffRpmStats.get(ent.getKey());
+                long screenOffTimeMs = screenOffTimer != null
+                        ? (screenOffTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : 0;
+                int screenOffCount = screenOffTimer != null
+                        ? screenOffTimer.getCountLocked(which) : 0;
+                if (SCREEN_OFF_RPM_STATS_ENABLED) {
+                    dumpLine(pw, 0 /* uid */, category, RESOURCE_POWER_MANAGER_DATA,
+                            "\"" + ent.getKey() + "\"", timeMs, count, screenOffTimeMs,
+                            screenOffCount);
+                } else {
+                    dumpLine(pw, 0 /* uid */, category, RESOURCE_POWER_MANAGER_DATA,
+                            "\"" + ent.getKey() + "\"", timeMs, count);
+                }
+            }
+        }
+
         final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
         helper.create(this);
         helper.refreshStats(which, UserHandle.USER_ALL);
@@ -4570,24 +4612,56 @@
         }
 
         final LongSparseArray<? extends Timer> mMemoryStats = getKernelMemoryStats();
-        pw.println("Memory Stats");
-        for (int i = 0; i < mMemoryStats.size(); i++) {
-            sb.setLength(0);
-            sb.append("Bandwidth ");
-            sb.append(mMemoryStats.keyAt(i));
-            sb.append(" Time ");
-            sb.append(mMemoryStats.valueAt(i).getTotalTimeLocked(rawRealtime, which));
-            pw.println(sb.toString());
+        if (mMemoryStats.size() > 0) {
+            pw.println("  Memory Stats");
+            for (int i = 0; i < mMemoryStats.size(); i++) {
+                sb.setLength(0);
+                sb.append("  Bandwidth ");
+                sb.append(mMemoryStats.keyAt(i));
+                sb.append(" Time ");
+                sb.append(mMemoryStats.valueAt(i).getTotalTimeLocked(rawRealtime, which));
+                pw.println(sb.toString());
+            }
+            pw.println();
+        }
+
+        final Map<String, ? extends Timer> rpmStats = getRpmStats();
+        if (rpmStats.size() > 0) {
+            pw.print(prefix); pw.println("  Resource Power Manager Stats");
+            if (rpmStats.size() > 0) {
+                for (Map.Entry<String, ? extends Timer> ent : rpmStats.entrySet()) {
+                    final String timerName = ent.getKey();
+                    final Timer timer = ent.getValue();
+                    printTimer(pw, sb, timer, rawRealtime, which, prefix, timerName);
+                }
+            }
+            pw.println();
+        }
+        if (SCREEN_OFF_RPM_STATS_ENABLED) {
+            final Map<String, ? extends Timer> screenOffRpmStats = getScreenOffRpmStats();
+            if (screenOffRpmStats.size() > 0) {
+                pw.print(prefix);
+                pw.println("  Resource Power Manager Stats for when screen was off");
+                if (screenOffRpmStats.size() > 0) {
+                    for (Map.Entry<String, ? extends Timer> ent : screenOffRpmStats.entrySet()) {
+                        final String timerName = ent.getKey();
+                        final Timer timer = ent.getValue();
+                        printTimer(pw, sb, timer, rawRealtime, which, prefix, timerName);
+                    }
+                }
+                pw.println();
+            }
         }
 
         final long[] cpuFreqs = getCpuFreqs();
         if (cpuFreqs != null) {
             sb.setLength(0);
-            sb.append("CPU freqs:");
+            sb.append("  CPU freqs:");
             for (int i = 0; i < cpuFreqs.length; ++i) {
                 sb.append(" " + cpuFreqs[i]);
             }
             pw.println(sb.toString());
+            pw.println();
         }
 
         for (int iu=0; iu<NU; iu++) {
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 3e07143..3b6df5d 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -791,7 +791,7 @@
 
             /**
              * Detect when an {@link java.io.Closeable} or other
-             * object with a explict termination method is finalized
+             * object with an explicit termination method is finalized
              * without having been closed.
              *
              * <p>You always want to explicitly close such objects to
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 81e8680..54f587e 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5159,17 +5159,39 @@
         public static final String ALLOW_MOCK_LOCATION = "mock_location";
 
         /**
-         * A 64-bit number (as a hex string) that is randomly
-         * generated when the user first sets up the device and should remain
-         * constant for the lifetime of the user's device. The value may
-         * change if a factory reset is performed on the device.
-         * <p class="note"><strong>Note:</strong> When a device has <a
-         * href="{@docRoot}about/versions/android-4.2.html#MultipleUsers">multiple users</a>
-         * (available on certain devices running Android 4.2 or higher), each user appears as a
-         * completely separate device, so the {@code ANDROID_ID} value is unique to each
-         * user.</p>
+         * On Android 8.0 (API level 26) and higher versions of the platform,
+         * a 64-bit number (expressed as a hexadecimal string), unique to
+         * each combination of app-signing key, user, and device.
+         * Values of {@code ANDROID_ID} are scoped by signing key and user.
+         * The value may change if a factory reset is performed on the
+         * device or if an APK signing key changes.
          *
-         * <p class="note"><strong>Note:</strong> If the caller is an Instant App the id is scoped
+         * For more information about how the platform handles {@code ANDROID_ID}
+         * in Android 8.0 (API level 26) and higher, see <a
+         * href="{@docRoot}preview/behavior-changes.html#privacy-all">
+         * Android 8.0 Behavior Changes</a>.
+         *
+         * <p class="note"><strong>Note:</strong> For apps that were installed
+         * prior to updating the device to a version of Android 8.0
+         * (API level 26) or higher, the value of {@code ANDROID_ID} changes
+         * if the app is uninstalled and then reinstalled after the OTA.
+         * To preserve values across uninstalls after an OTA to Android 8.0
+         * or higher, developers can use
+         * <a href="{@docRoot}guide/topics/data/keyvaluebackup.html">
+         * Key/Value Backup</a>.</p>
+         *
+         * <p>In versions of the platform lower than Android 8.0 (API level 26),
+         * a 64-bit number (expressed as a hexadecimal string) that is randomly
+         * generated when the user first sets up the device and should remain
+         * constant for the lifetime of the user's device.
+         *
+         * On devices that have
+         * <a href="{@docRoot}about/versions/android-4.2.html#MultipleUsers">
+         * multiple users</a>, each user appears as a
+         * completely separate device, so the {@code ANDROID_ID} value is
+         * unique to each user.</p>
+         *
+         * <p class="note"><strong>Note:</strong> If the caller is an Instant App the ID is scoped
          * to the Instant App, it is generated when the Instant App is first installed and reset if
          * the user clears the Instant App.
          */
@@ -8533,6 +8555,16 @@
         public static final String NETWORK_SCORING_UI_ENABLED = "network_scoring_ui_enabled";
 
         /**
+         * Value to specify how long in milliseconds to retain seen score cache curves to be used
+         * when generating SSID only bases score curves.
+         *
+         * Type: long
+         * @hide
+         */
+        public static final String SPEED_LABEL_CACHE_EVICTION_AGE_MILLIS =
+                "speed_label_cache_eviction_age_millis";
+
+        /**
          * Value to specify if network recommendations from
          * {@link com.android.server.NetworkScoreService} are enabled.
          *
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 1dcaef4..3e08dcf 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -51,6 +51,7 @@
  *       Settings screen).
  * </ol>
  *
+ * <a name="BasicUsage"></a>
  * <h3>Basic usage</h3>
  *
  * <p>The basic autofill process is defined by the workflow below:
@@ -122,12 +123,14 @@
  * each {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} received - if it
  * doesn't, the request will eventually time out and be discarded by the Android System.
  *
+ * <a name="SavingUserData"></a>
  * <h3>Saving user data</h3>
  *
  * <p>If the service is also interested on saving the data filled by the user, it must set a
  * {@link SaveInfo} object in the {@link FillResponse}. See {@link SaveInfo} for more details and
  * examples.
  *
+ * <a name="UserAuthentication"></a>
  * <h3>User authentication</h3>
  *
  * <p>The service can provide an extra degree of security by requiring the user to authenticate
@@ -164,6 +167,7 @@
  * credentials in "vaults": the first response would contain fake datasets with the vault names,
  * and the subsequent response would contain the app credentials stored in that vault.
  *
+ * <a name="DataPartioning"></a>
  * <h3>Data partitioning</h3>
  *
  * <p>The autofillable views in a screen should be grouped in logical groups called "partitions".
@@ -243,6 +247,7 @@
  * <p>When the service returns multiple {@link FillResponse}, the last one overrides the previous;
  * that's why the {@link SaveInfo} in the 2nd request above has the info for both partitions.
  *
+ * <a name="PackageVerification"></a>
  * <h3>Package verification</h3>
  *
  * <p>When autofilling app-specific data (like username and password), the service must verify
@@ -270,9 +275,16 @@
  *   }
  *   return hash.toString();
  * }
- *
  * </pre>
  *
+ * <p>If the service did not store the signing certificates data the first time the data was saved
+ * &mdash; for example, because the data was created by a previous version of the app that did not
+ * use the Autofill Framework &mdash; the service should warn the user that the authenticity of the
+ * app cannot be confirmed (see an example on how to show such warning in the
+ * <a href="#WebSecurityDisclaimer">Web security</a> section below), and if the user agrees,
+ * then the service could save the data from the signing ceriticates for future use.
+ *
+ * <a name="IgnoringViews"></a>
  * <h3>Ignoring views</h3>
  *
  * <p>If the service find views that cannot be autofilled (for example, a text field representing
@@ -281,6 +293,7 @@
  * a new {@link #onFillRequest(FillRequest, CancellationSignal, FillCallback)} when these views are
  * focused.
  *
+ * <a name="WebSecurity"></a>
  * <h3>Web security</h3>
  *
  * <p>When handling autofill requests that represent web pages (typically
@@ -313,6 +326,7 @@
  * }
  * </pre>
  *
+ * <a name="WebSecurityDisclaimer"></a>
  * <p>If the association between the web domain and app package cannot be verified through the steps
  * above, but the service thinks that it is appropriate to fill persisted credentials that are
  * stored for the web domain, the service should warn the user about the potential data
diff --git a/core/java/android/service/autofill/CharSequenceTransformation.java b/core/java/android/service/autofill/CharSequenceTransformation.java
index 8ab856e..2413e97 100644
--- a/core/java/android/service/autofill/CharSequenceTransformation.java
+++ b/core/java/android/service/autofill/CharSequenceTransformation.java
@@ -86,7 +86,7 @@
             }
             try {
                 final Matcher matcher = field.first.matcher(value);
-                if (!matcher.matches()) {
+                if (!matcher.find()) {
                     if (sDebug) Log.d(TAG, "match for " + field.first + " failed on id " + id);
                     return;
                 }
diff --git a/core/java/android/service/autofill/FillEventHistory.java b/core/java/android/service/autofill/FillEventHistory.java
index f7dc1c5..768e743 100644
--- a/core/java/android/service/autofill/FillEventHistory.java
+++ b/core/java/android/service/autofill/FillEventHistory.java
@@ -22,8 +22,7 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.view.autofill.AutofillId;
-import android.widget.RemoteViews;
+import android.view.autofill.AutofillManager;
 
 import com.android.internal.util.Preconditions;
 
@@ -81,7 +80,7 @@
     /**
      * Returns the client state set in the previous {@link FillResponse}.
      *
-     * <p><b>NOTE: </b>the state is associated with the app that was autofilled in the previous
+     * <p><b>Note: </b>the state is associated with the app that was autofilled in the previous
      * {@link AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)}
      * , which is not necessary the same app being autofilled now.
      */
@@ -148,6 +147,14 @@
     public static final class Event {
         /**
          * A dataset was selected. The dataset selected can be read from {@link #getDatasetId()}.
+         *
+         * <p><b>Note: </b>on Android {@link android.os.Build.VERSION_CODES#O}, this event was also
+         * incorrectly reported after a
+         * {@link Dataset.Builder#setAuthentication(IntentSender) dataset authentication} was
+         * selected and the service returned a dataset in the
+         * {@link AutofillManager#EXTRA_AUTHENTICATION_RESULT} of the activity launched from that
+         * {@link IntentSender}. This behavior was fixed on Android
+         * {@link android.os.Build.VERSION_CODES#O_MR1}.
          */
         public static final int TYPE_DATASET_SELECTED = 0;
 
@@ -158,8 +165,8 @@
         public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1;
 
         /**
-         * A {@link FillResponse.Builder#setAuthentication(AutofillId[], IntentSender, RemoteViews)
-         * fill response authentication} was selected.
+         * A {@link FillResponse.Builder#setAuthentication(android.view.autofill.AutofillId[],
+         * IntentSender, android.widget.RemoteViews) fill response authentication} was selected.
          */
         public static final int TYPE_AUTHENTICATION_SELECTED = 2;
 
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
index 1c32fe0..3a84224 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Bundle;
-import android.os.CancellationSignal;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.view.View;
@@ -38,7 +37,7 @@
  * interesting for saving and what are the possible ways to fill the inputs on
  * the screen if applicable.
  *
- * @see AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)
+ * @see AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)
  */
 public final class FillRequest implements Parcelable {
 
@@ -122,9 +121,14 @@
         return mContexts;
     }
 
+    @Override
+    public String toString() {
+        return "FillRequest: [id=" + mId + ", flags=" + mFlags + ", ctxts= " + mContexts + "]";
+    }
+
     /**
      * Gets the extra client state returned from the last {@link
-     * AutofillService#onFillRequest(FillRequest, CancellationSignal, FillCallback)
+     * AutofillService#onFillRequest(FillRequest, android.os.CancellationSignal, FillCallback)
      * fill request}, so the service can use it for state management.
      *
      * <p>Once a {@link AutofillService#onSaveRequest(SaveRequest, SaveCallback)
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index 3b09c67..6d8a959 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -148,10 +148,12 @@
          * {@link android.view.autofill.AutofillManager#EXTRA_ASSIST_STRUCTURE screen
          * content} and your {@link android.view.autofill.AutofillManager#EXTRA_CLIENT_STATE
          * client state}. Once you complete your authentication flow you should set the
-         * {@link Activity} result to {@link android.app.Activity#RESULT_OK} and provide the fully
-         * populated {@link FillResponse response} by setting it to the
-         * {@link android.view.autofill.AutofillManager#EXTRA_AUTHENTICATION_RESULT} extra.
-         * For example, if you provided an empty {@link FillResponse resppnse} because the
+         * {@link Activity} result to {@link android.app.Activity#RESULT_OK} and set the
+         * {@link android.view.autofill.AutofillManager#EXTRA_AUTHENTICATION_RESULT} extra
+         * with the fully populated {@link FillResponse response} (or {@code null} if the screen
+         * cannot be autofilled).
+         *
+         * <p>For example, if you provided an empty {@link FillResponse response} because the
          * user's data was locked and marked that the response needs an authentication then
          * in the response returned if authentication succeeds you need to provide all
          * available data sets some of which may need to be further authenticated, for
diff --git a/core/java/android/service/oemlock/IOemLockService.aidl b/core/java/android/service/oemlock/IOemLockService.aidl
index 682e7ee..d5e10d6 100644
--- a/core/java/android/service/oemlock/IOemLockService.aidl
+++ b/core/java/android/service/oemlock/IOemLockService.aidl
@@ -28,7 +28,6 @@
     void setOemUnlockAllowedByUser(boolean allowed);
     boolean isOemUnlockAllowedByUser();
 
-    boolean canUserAllowOemUnlock();
     boolean isOemUnlockAllowed();
     boolean isDeviceOemUnlocked();
 }
diff --git a/core/java/android/service/oemlock/OemLockManager.java b/core/java/android/service/oemlock/OemLockManager.java
index 3a56d9f..f0d6603 100644
--- a/core/java/android/service/oemlock/OemLockManager.java
+++ b/core/java/android/service/oemlock/OemLockManager.java
@@ -118,24 +118,6 @@
     }
 
     /**
-     * Returns whether all parties other than the user allow OEM unlock meaning the user can
-     * directly control whether or not the device can be OEM unlocked.
-     *
-     * If this is true, {@link #isOemUnlockAllowedByUser} is the same as {@link #isOemUnlockAllowed}
-     *
-     * @return Whether the user can directly control whether the device can be OEM unlocked.
-     *
-     * @hide
-     */
-    public boolean canUserAllowOemUnlock() {
-        try {
-            return mService.canUserAllowOemUnlock();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
      * @return Whether the bootloader is able to OEM unlock the device.
      *
      * @hide
diff --git a/core/java/android/text/InputType.java b/core/java/android/text/InputType.java
index 8967b70..f38482e 100644
--- a/core/java/android/text/InputType.java
+++ b/core/java/android/text/InputType.java
@@ -182,9 +182,9 @@
      * want the IME to correct typos.
      * Note the contrast with {@link #TYPE_TEXT_FLAG_AUTO_CORRECT} and
      * {@link #TYPE_TEXT_FLAG_AUTO_COMPLETE}:
-     * {@code TYPE_TEXT_FLAG_NO_SUGGESTIONS} means the IME should never
+     * {@code TYPE_TEXT_FLAG_NO_SUGGESTIONS} means the IME does not need to
      * show an interface to display suggestions. Most IMEs will also take this to
-     * mean they should not try to auto-correct what the user is typing.
+     * mean they do not need to try to auto-correct what the user is typing.
      */
     public static final int TYPE_TEXT_FLAG_NO_SUGGESTIONS = 0x00080000;
 
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index fc56455..2c83fc4 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -32,6 +32,7 @@
 import android.text.TextUtils;
 import android.view.View;
 
+import java.lang.reflect.Constructor;
 import java.math.BigDecimal;
 import java.util.Locale;
 
@@ -194,13 +195,29 @@
 
     /**
      * ICU doesn't support PETABYTE yet. Fake it so that we can treat all units the same way.
-     * {@hide}
      */
-    public static final MeasureUnit PETABYTE = MeasureUnit.internalGetInstance(
-            "digital", "petabyte");
+    private static final MeasureUnit PETABYTE = createPetaByte();
 
-    /** {@hide} */
-    public static class RoundedBytesResult {
+    /**
+     * Create a petabyte MeasureUnit without registering it with ICU.
+     * ICU doesn't support user-create MeasureUnit and the only public (but hidden) method to do so
+     * is {@link MeasureUnit#internalGetInstance(String, String)} which also registers the unit as
+     * an available type and thus leaks it to code that doesn't expect or support it.
+     * <p>This method uses reflection to create an instance of MeasureUnit to avoid leaking it. This
+     * instance is <b>only</b> to be used in this class.
+     */
+    private static MeasureUnit createPetaByte() {
+        try {
+            Constructor<MeasureUnit> constructor = MeasureUnit.class
+                    .getDeclaredConstructor(String.class, String.class);
+            constructor.setAccessible(true);
+            return constructor.newInstance("digital", "petabyte");
+        } catch (ReflectiveOperationException e) {
+            throw new RuntimeException("Failed to create petabyte MeasureUnit", e);
+        }
+    }
+
+    private static class RoundedBytesResult {
         public final float value;
         public final MeasureUnit units;
         public final int fractionDigits;
@@ -218,7 +235,7 @@
          * Returns a RoundedBytesResult object based on the input size in bytes and the rounding
          * flags. The result can be used for formatting.
          */
-        public static RoundedBytesResult roundBytes(long sizeBytes, int flags) {
+        static RoundedBytesResult roundBytes(long sizeBytes, int flags) {
             final boolean isNegative = (sizeBytes < 0);
             float result = isNegative ? -sizeBytes : sizeBytes;
             MeasureUnit units = MeasureUnit.BYTE;
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index af26a88..74555de 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -574,10 +574,10 @@
         switch (direction) {
             case View.FOCUS_LEFT:
             case View.FOCUS_RIGHT:
-                return (rect2.bottom >= rect1.top) && (rect2.top <= rect1.bottom);
+                return (rect2.bottom > rect1.top) && (rect2.top < rect1.bottom);
             case View.FOCUS_UP:
             case View.FOCUS_DOWN:
-                return (rect2.right >= rect1.left) && (rect2.left <= rect1.right);
+                return (rect2.right > rect1.left) && (rect2.left < rect1.right);
         }
         throw new IllegalArgumentException("direction must be one of "
                 + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT}.");
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 829b2b7..a2147b7 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -804,8 +804,11 @@
     public static final int KEYCODE_SYSTEM_NAVIGATION_LEFT = 282;
     /** Key code constant: Consumed by the system for navigation right */
     public static final int KEYCODE_SYSTEM_NAVIGATION_RIGHT = 283;
+    /** Key code constant: Show all apps
+     * @hide */
+    public static final int KEYCODE_ALL_APPS = 284;
 
-    private static final int LAST_KEYCODE = KEYCODE_SYSTEM_NAVIGATION_RIGHT;
+    private static final int LAST_KEYCODE = KEYCODE_ALL_APPS;
 
     // NOTE: If you add a new keycode here you must also add it to:
     //  isSystem()
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 1d206ab..cac27af 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
 import static android.view.WindowManagerPolicy.APPLICATION_MEDIA_OVERLAY_SUBLAYER;
 import static android.view.WindowManagerPolicy.APPLICATION_MEDIA_SUBLAYER;
 import static android.view.WindowManagerPolicy.APPLICATION_PANEL_SUBLAYER;
@@ -871,6 +872,31 @@
         return callbacks;
     }
 
+    /**
+     * This method still exists only for compatibility reasons because some applications have relied
+     * on this method via reflection. See Issue 36345857 for details.
+     *
+     * @deprecated No platform code is using this method anymore.
+     * @hide
+     */
+    @Deprecated
+    public void setWindowType(int type) {
+        if (getContext().getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.O) {
+            throw new UnsupportedOperationException(
+                    "SurfaceView#setWindowType() has never been a public API.");
+        }
+
+        if (type == TYPE_APPLICATION_PANEL) {
+            Log.e(TAG, "If you are calling SurfaceView#setWindowType(TYPE_APPLICATION_PANEL) "
+                    + "just to make the SurfaceView to be placed on top of its window, you must "
+                    + "call setZOrderOnTop(true) instead.", new Throwable());
+            setZOrderOnTop(true);
+            return;
+        }
+        Log.e(TAG, "SurfaceView#setWindowType(int) is deprecated and now does nothing. "
+                + "type=" + type, new Throwable());
+    }
+
     private void runOnUiThread(Runnable runnable) {
         Handler handler = getHandler();
         if (handler != null && handler.getLooper() != Looper.myLooper()) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 73fc437..166d6b7 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -127,6 +127,7 @@
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Calendar;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -1078,6 +1079,29 @@
      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}</code>).
      *
+     * <p>When annotating a view with this hint, it's recommended to use a date autofill value to
+     * avoid ambiguity when the autofill service provides a value for it. To understand why a
+     * value can be ambiguous, consider "April of 2020", which could be represented as either of
+     * the following options:
+     *
+     * <ul>
+     *   <li>{@code "04/2020"}
+     *   <li>{@code "4/2020"}
+     *   <li>{@code "2020/04"}
+     *   <li>{@code "2020/4"}
+     *   <li>{@code "April/2020"}
+     *   <li>{@code "Apr/2020"}
+     * </ul>
+     *
+     * <p>You define a date autofill value for the view by overriding the following methods:
+     *
+     * <ol>
+     *   <li>{@link #getAutofillType()} to return {@link #AUTOFILL_TYPE_DATE}.
+     *   <li>{@link #getAutofillValue()} to return a
+     *       {@link AutofillValue#forDate(long) date autofillvalue}.
+     *   <li>{@link #autofill(AutofillValue)} to expect a data autofillvalue.
+     * </ol>
+     *
      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
      */
     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
@@ -1090,6 +1114,22 @@
      * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
      * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}</code>).
      *
+     * <p>When annotating a view with this hint, it's recommended to use a text autofill value
+     * whose value is the numerical representation of the month, starting on {@code 1} to avoid
+     * ambiguity when the autofill service provides a value for it. To understand why a
+     * value can be ambiguous, consider "January", which could be represented as either of
+     *
+     * <ul>
+     *   <li>{@code "1"}: recommended way.
+     *   <li>{@code "0"}: if following the {@link Calendar#MONTH} convention.
+     *   <li>{@code "January"}: full name, in English.
+     *   <li>{@code "jan"}: abbreviated name, in English.
+     *   <li>{@code "Janeiro"}: full name, in another language.
+     * </ul>
+     *
+     * <p>Another recommended approach is to use a date autofill value - see
+     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE} for more details.
+     *
      * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
      */
     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
@@ -7618,6 +7658,10 @@
      *   <li>Call
      *    {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)}
      *       when the value of a virtual child changed.
+     *   <li>Call
+     *    {@link
+     *    android.view.autofill.AutofillManager#notifyViewVisibilityChanged(View, int, boolean)}
+     *       when the visibility of a virtual child changed.
      *   <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
      *       changed and the current context should be committed (for example, when the user tapped
      *       a {@code SUBMIT} button in an HTML page).
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 61cbce9..f888ba2 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -37,14 +37,13 @@
 import android.service.autofill.FillEventHistory;
 import android.util.ArrayMap;
 import android.util.ArraySet;
-import android.util.DebugUtils;
 import android.util.Log;
 import android.util.SparseArray;
 import android.view.View;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
@@ -202,9 +201,12 @@
      * Initial state of the autofill context, set when there is no session (i.e., when
      * {@link #mSessionId} is {@link #NO_SESSION}).
      *
+     * <p>In this state, app callbacks (such as {@link #notifyViewEntered(View)}) are notified to
+     * the server.
+     *
      * @hide
      */
-    public static final int STATE_UNKNOWN = 1;
+    public static final int STATE_UNKNOWN = 0;
 
     /**
      * State where the autofill context hasn't been {@link #commit() finished} nor
@@ -212,7 +214,18 @@
      *
      * @hide
      */
-    public static final int STATE_ACTIVE = 2;
+    public static final int STATE_ACTIVE = 1;
+
+    /**
+     * State where the autofill context was finished by the server because the autofill
+     * service could not autofill the page.
+     *
+     * <p>In this state, most apps callback (such as {@link #notifyViewEntered(View)}) are ignored,
+     * exception {@link #requestAutofill(View)} (and {@link #requestAutofill(View, int, Rect)}).
+     *
+     * @hide
+     */
+    public static final int STATE_FINISHED = 2;
 
     /**
      * State where the autofill context has been {@link #commit() finished} but the server still has
@@ -220,7 +233,7 @@
      *
      * @hide
      */
-    public static final int STATE_SHOWING_SAVE_UI = 4;
+    public static final int STATE_SHOWING_SAVE_UI = 3;
 
     /**
      * Makes an authentication id from a request id and a dataset id.
@@ -559,6 +572,14 @@
         }
         AutofillCallback callback = null;
         synchronized (mLock) {
+            if (isFinishedLocked() && (flags & FLAG_MANUAL_REQUEST) == 0) {
+                if (sVerbose) {
+                    Log.v(TAG, "notifyViewEntered(flags=" + flags + ", view=" + view
+                            + "): ignored on state " + getStateAsStringLocked());
+                }
+                return;
+            }
+
             ensureServiceClientAddedIfNeededLocked();
 
             if (!mEnabled) {
@@ -682,6 +703,14 @@
         }
         AutofillCallback callback = null;
         synchronized (mLock) {
+            if (isFinishedLocked() && (flags & FLAG_MANUAL_REQUEST) == 0) {
+                if (sVerbose) {
+                    Log.v(TAG, "notifyViewEntered(flags=" + flags + ", view=" + view
+                            + ", virtualId=" + virtualId
+                            + "): ignored on state " + getStateAsStringLocked());
+                }
+                return;
+            }
             ensureServiceClientAddedIfNeededLocked();
 
             if (!mEnabled) {
@@ -765,6 +794,10 @@
             }
 
             if (!mEnabled || !isActiveLocked()) {
+                if (sVerbose && mEnabled) {
+                    Log.v(TAG, "notifyValueChanged(" + view + "): ignoring on state "
+                            + getStateAsStringLocked());
+                }
                 return;
             }
 
@@ -950,10 +983,13 @@
             @NonNull AutofillValue value, int flags) {
         if (sVerbose) {
             Log.v(TAG, "startSessionLocked(): id=" + id + ", bounds=" + bounds + ", value=" + value
-                    + ", flags=" + flags + ", state=" + mState);
+                    + ", flags=" + flags + ", state=" + getStateAsStringLocked());
         }
-        if (mState != STATE_UNKNOWN) {
-            if (sDebug) Log.d(TAG, "not starting session for " + id + " on state " + mState);
+        if (mState != STATE_UNKNOWN && (flags & FLAG_MANUAL_REQUEST) == 0) {
+            if (sVerbose) {
+                Log.v(TAG, "not automatically starting session for " + id
+                        + " on state " + getStateAsStringLocked());
+            }
             return;
         }
         try {
@@ -973,7 +1009,7 @@
     }
 
     private void finishSessionLocked() {
-        if (sVerbose) Log.v(TAG, "finishSessionLocked(): " + mState);
+        if (sVerbose) Log.v(TAG, "finishSessionLocked(): " + getStateAsStringLocked());
 
         if (!isActiveLocked()) return;
 
@@ -987,7 +1023,7 @@
     }
 
     private void cancelSessionLocked() {
-        if (sVerbose) Log.v(TAG, "cancelSessionLocked(): " + mState);
+        if (sVerbose) Log.v(TAG, "cancelSessionLocked(): " + getStateAsStringLocked());
 
         if (!isActiveLocked()) return;
 
@@ -1245,10 +1281,10 @@
                 }
             }
 
-            final LogMaker log = new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_DATASET_APPLIED);
-            log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VALUES, itemCount);
-            log.addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_VIEWS_FILLED,
-                    numApplied);
+            final LogMaker log = new LogMaker(MetricsEvent.AUTOFILL_DATASET_APPLIED)
+                    .setPackageName(mContext.getPackageName())
+                    .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_VALUES, itemCount)
+                    .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_VIEWS_FILLED, numApplied);
             mMetricsLogger.write(log);
         }
     }
@@ -1306,6 +1342,14 @@
         }
     }
 
+    private void setSessionFinished() {
+        if (sVerbose) Log.v(TAG, "setSessionFinished()");
+        synchronized (mLock) {
+            resetSessionLocked();
+            mState = STATE_FINISHED;
+        }
+    }
+
     private void requestHideFillUi(AutofillId id) {
         final View anchor = findView(id);
         if (sVerbose) Log.v(TAG, "requestHideFillUi(" + id + "): anchor = " + anchor);
@@ -1341,7 +1385,11 @@
         }
     }
 
-    private void notifyNoFillUi(int sessionId, AutofillId id) {
+    private void notifyNoFillUi(int sessionId, AutofillId id, boolean sessionFinished) {
+        if (sVerbose) {
+            Log.v(TAG, "notifyNoFillUi(): sessionId=" + sessionId + ", autofillId=" + id
+                    + ", finished=" + sessionFinished);
+        }
         final View anchor = findView(id);
         if (anchor == null) {
             return;
@@ -1361,7 +1409,11 @@
             } else {
                 callback.onAutofillEvent(anchor, AutofillCallback.EVENT_INPUT_UNAVAILABLE);
             }
+        }
 
+        if (sessionFinished) {
+            // Callback call was "hijacked" to also update the session state.
+            setSessionFinished();
         }
     }
 
@@ -1434,8 +1486,7 @@
         pw.print(outerPrefix); pw.println("AutofillManager:");
         final String pfx = outerPrefix + "  ";
         pw.print(pfx); pw.print("sessionId: "); pw.println(mSessionId);
-        pw.print(pfx); pw.print("state: "); pw.println(
-                DebugUtils.flagsToString(AutofillManager.class, "STATE_", mState));
+        pw.print(pfx); pw.print("state: "); pw.println(getStateAsStringLocked());
         pw.print(pfx); pw.print("enabled: "); pw.println(mEnabled);
         pw.print(pfx); pw.print("hasService: "); pw.println(mService != null);
         pw.print(pfx); pw.print("hasCallback: "); pw.println(mCallback != null);
@@ -1452,10 +1503,29 @@
         pw.print(pfx); pw.print("fillable ids: "); pw.println(mFillableIds);
     }
 
+    private String getStateAsStringLocked() {
+        switch (mState) {
+            case STATE_UNKNOWN:
+                return "STATE_UNKNOWN";
+            case STATE_ACTIVE:
+                return "STATE_ACTIVE";
+            case STATE_FINISHED:
+                return "STATE_FINISHED";
+            case STATE_SHOWING_SAVE_UI:
+                return "STATE_SHOWING_SAVE_UI";
+            default:
+                return "INVALID:" + mState;
+        }
+    }
+
     private boolean isActiveLocked() {
         return mState == STATE_ACTIVE;
     }
 
+    private boolean isFinishedLocked() {
+        return mState == STATE_FINISHED;
+    }
+
     private void post(Runnable runnable) {
         final AutofillClient client = getClientLocked();
         if (client == null) {
@@ -1787,10 +1857,10 @@
         }
 
         @Override
-        public void notifyNoFillUi(int sessionId, AutofillId id) {
+        public void notifyNoFillUi(int sessionId, AutofillId id, boolean sessionFinished) {
             final AutofillManager afm = mAfm.get();
             if (afm != null) {
-                afm.post(() -> afm.notifyNoFillUi(sessionId, id));
+                afm.post(() -> afm.notifyNoFillUi(sessionId, id, sessionFinished));
             }
         }
 
@@ -1823,7 +1893,15 @@
         public void setSaveUiState(int sessionId, boolean shown) {
             final AutofillManager afm = mAfm.get();
             if (afm != null) {
-                afm.post(() ->afm.setSaveUiState(sessionId, shown));
+                afm.post(() -> afm.setSaveUiState(sessionId, shown));
+            }
+        }
+
+        @Override
+        public void setSessionFinished() {
+            final AutofillManager afm = mAfm.get();
+            if (afm != null) {
+                afm.post(() -> afm.setSessionFinished());
             }
         }
     }
diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
index 0eae858..db6855a 100644
--- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl
+++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
@@ -67,9 +67,9 @@
     void requestHideFillUi(int sessionId, in AutofillId id);
 
     /**
-     * Notifies no fill UI will be shown.
+     * Notifies no fill UI will be shown, and also mark the state as finished if necessary.
      */
-    void notifyNoFillUi(int sessionId, in AutofillId id);
+    void notifyNoFillUi(int sessionId, in AutofillId id, boolean sessionFinished);
 
     /**
      * Starts the provided intent sender.
@@ -80,4 +80,10 @@
      * Sets the state of the Autofill Save UI for a given session.
      */
    void setSaveUiState(int sessionId, boolean shown);
+
+   /**
+     * Marks the state of the session as finished (because the AutofillService returned a null
+     * FillResponse).
+     */
+   void setSessionFinished();
 }
diff --git a/core/java/android/view/textclassifier/TextClassification.java b/core/java/android/view/textclassifier/TextClassification.java
index fa7b9a5..1849368 100644
--- a/core/java/android/view/textclassifier/TextClassification.java
+++ b/core/java/android/view/textclassifier/TextClassification.java
@@ -261,7 +261,7 @@
          * @hide
          */
         Builder setVersionInfo(@NonNull String versionInfo) {
-            mVersionInfo = Preconditions.checkNotNull(mVersionInfo);
+            mVersionInfo = Preconditions.checkNotNull(versionInfo);
             return this;
         }
 
diff --git a/core/java/android/view/textclassifier/TextSelection.java b/core/java/android/view/textclassifier/TextSelection.java
index 085dd32..11ebe83 100644
--- a/core/java/android/view/textclassifier/TextSelection.java
+++ b/core/java/android/view/textclassifier/TextSelection.java
@@ -169,7 +169,7 @@
          * @hide
          */
         Builder setVersionInfo(@NonNull String versionInfo) {
-            mVersionInfo = Preconditions.checkNotNull(mVersionInfo);
+            mVersionInfo = Preconditions.checkNotNull(versionInfo);
             return this;
         }
 
diff --git a/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java b/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java
index 45baf91..b6034d1 100644
--- a/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java
+++ b/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java
@@ -42,17 +42,16 @@
 //TODO: Do not allow any crashes from this class.
 public final class SmartSelectionEventTracker {
 
-    private static final String LOG_TAG = "SmartSelectionEventTracker";
+    private static final String LOG_TAG = "SmartSelectEventTracker";
     private static final boolean DEBUG_LOG_ENABLED = true;
 
-    private static final int START_EVENT_DELTA = MetricsEvent.NOTIFICATION_SINCE_CREATE_MILLIS;
-    private static final int PREV_EVENT_DELTA = MetricsEvent.NOTIFICATION_SINCE_UPDATE_MILLIS;
-    private static final int ENTITY_TYPE = MetricsEvent.NOTIFICATION_TAG;
-    private static final int INDEX = MetricsEvent.NOTIFICATION_SHADE_INDEX;
-    private static final int TAG = MetricsEvent.FIELD_CLASS_NAME;
-    private static final int SMART_INDICES = MetricsEvent.FIELD_GESTURE_LENGTH;
-    private static final int EVENT_INDICES = MetricsEvent.FIELD_CONTEXT;
-    private static final int SESSION_ID = MetricsEvent.FIELD_INSTANT_APP_LAUNCH_TOKEN;
+    private static final int START_EVENT_DELTA = MetricsEvent.FIELD_SELECTION_SINCE_START;
+    private static final int PREV_EVENT_DELTA = MetricsEvent.FIELD_SELECTION_SINCE_PREVIOUS;
+    private static final int INDEX = MetricsEvent.FIELD_SELECTION_SESSION_INDEX;
+    private static final int VERSION_TAG = MetricsEvent.FIELD_SELECTION_VERSION_TAG;
+    private static final int SMART_INDICES = MetricsEvent.FIELD_SELECTION_SMART_RANGE;
+    private static final int EVENT_INDICES = MetricsEvent.FIELD_SELECTION_RANGE;
+    private static final int SESSION_ID = MetricsEvent.FIELD_SELECTION_SESSION_ID;
 
     private static final String ZERO = "0";
     private static final String TEXTVIEW = "textview";
@@ -84,6 +83,7 @@
     private long mSessionStartTime;
     private long mLastEventTime;
     private boolean mSmartSelectionTriggered;
+    private String mVersionTag;
 
     public SmartSelectionEventTracker(@NonNull Context context, @WidgetType int widgetType) {
         mWidgetType = widgetType;
@@ -98,7 +98,8 @@
     public void logEvent(@NonNull SelectionEvent event) {
         Preconditions.checkNotNull(event);
 
-        if (event.mEventType != SelectionEvent.EventType.SELECTION_STARTED && mSessionId == null) {
+        if (event.mEventType != SelectionEvent.EventType.SELECTION_STARTED && mSessionId == null
+                && DEBUG_LOG_ENABLED) {
             Log.d(LOG_TAG, "Selection session not yet started. Ignoring event");
             return;
         }
@@ -114,6 +115,7 @@
             case SelectionEvent.EventType.SMART_SELECTION_SINGLE:  // fall through
             case SelectionEvent.EventType.SMART_SELECTION_MULTI:
                 mSmartSelectionTriggered = true;
+                mVersionTag = getVersionTag(event);
                 mSmartIndices[0] = event.mStart;
                 mSmartIndices[1] = event.mEnd;
                 break;
@@ -132,16 +134,16 @@
     }
 
     private void writeEvent(SelectionEvent event, long now) {
-        final LogMaker log = new LogMaker(MetricsEvent.TEXT_SELECTION_MENU_ITEM_ASSIST)
+        final long prevEventDelta = mLastEventTime == 0 ? 0 : now - mLastEventTime;
+        final LogMaker log = new LogMaker(MetricsEvent.TEXT_SELECTION_SESSION)
                 .setType(getLogType(event))
-                .setSubtype(event.mEventType)
+                .setSubtype(getLogSubType(event))
                 .setPackageName(mContext.getPackageName())
                 .setTimestamp(now)
                 .addTaggedData(START_EVENT_DELTA, now - mSessionStartTime)
-                .addTaggedData(PREV_EVENT_DELTA, now - mLastEventTime)
-                .addTaggedData(ENTITY_TYPE, event.mEntityType)
+                .addTaggedData(PREV_EVENT_DELTA, prevEventDelta)
                 .addTaggedData(INDEX, mIndex)
-                .addTaggedData(TAG, getTag(event))
+                .addTaggedData(VERSION_TAG, mVersionTag)
                 .addTaggedData(SMART_INDICES, getSmartDelta())
                 .addTaggedData(EVENT_INDICES, getEventDelta(event))
                 .addTaggedData(SESSION_ID, mSessionId);
@@ -168,42 +170,120 @@
         mSessionStartTime = 0;
         mLastEventTime = 0;
         mSmartSelectionTriggered = false;
+        mVersionTag = getVersionTag(null);
         mSessionId = null;
     }
 
-    private int getLogType(SelectionEvent event) {
+    private static int getLogType(SelectionEvent event) {
         switch (event.mEventType) {
-            case SelectionEvent.EventType.SELECTION_STARTED:  // fall through
-            case SelectionEvent.EventType.SMART_SELECTION_SINGLE:  // fall through
-            case SelectionEvent.EventType.SMART_SELECTION_MULTI:  // fall through
-            case SelectionEvent.EventType.AUTO_SELECTION:
-                return MetricsEvent.TYPE_OPEN;
+            case SelectionEvent.ActionType.OVERTYPE:
+                return MetricsEvent.ACTION_TEXT_SELECTION_OVERTYPE;
+            case SelectionEvent.ActionType.COPY:
+                return MetricsEvent.ACTION_TEXT_SELECTION_COPY;
+            case SelectionEvent.ActionType.PASTE:
+                return MetricsEvent.ACTION_TEXT_SELECTION_PASTE;
+            case SelectionEvent.ActionType.CUT:
+                return MetricsEvent.ACTION_TEXT_SELECTION_CUT;
+            case SelectionEvent.ActionType.SHARE:
+                return MetricsEvent.ACTION_TEXT_SELECTION_SHARE;
+            case SelectionEvent.ActionType.SMART_SHARE:
+                return MetricsEvent.ACTION_TEXT_SELECTION_SMART_SHARE;
+            case SelectionEvent.ActionType.DRAG:
+                return MetricsEvent.ACTION_TEXT_SELECTION_DRAG;
             case SelectionEvent.ActionType.ABANDON:
-                return MetricsEvent.TYPE_CLOSE;
-        }
-        if (event.isActionType()) {
-            if (event.isTerminal() && mSmartSelectionTriggered) {
-                if (matchesSmartSelectionBounds(event)) {
-                    // Smart selection accepted.
-                    return MetricsEvent.TYPE_SUCCESS;
-                } else if (containsOriginalSelection(event)) {
-                    // Smart selection rejected.
-                    return MetricsEvent.TYPE_FAILURE;
-                }
-                // User changed the original selection entirely.
-            }
-            return MetricsEvent.TYPE_ACTION;
-        } else {
-            return MetricsEvent.TYPE_UPDATE;
+                return MetricsEvent.ACTION_TEXT_SELECTION_ABANDON;
+            case SelectionEvent.ActionType.OTHER:
+                return MetricsEvent.ACTION_TEXT_SELECTION_OTHER;
+            case SelectionEvent.ActionType.SELECT_ALL:
+                return MetricsEvent.ACTION_TEXT_SELECTION_SELECT_ALL;
+            case SelectionEvent.ActionType.RESET:
+                return MetricsEvent.ACTION_TEXT_SELECTION_RESET;
+            case SelectionEvent.EventType.SELECTION_STARTED:
+                return MetricsEvent.ACTION_TEXT_SELECTION_START;
+            case SelectionEvent.EventType.SELECTION_MODIFIED:
+                return MetricsEvent.ACTION_TEXT_SELECTION_MODIFY;
+            case SelectionEvent.EventType.SMART_SELECTION_SINGLE:
+                return MetricsEvent.ACTION_TEXT_SELECTION_SMART_SINGLE;
+            case SelectionEvent.EventType.SMART_SELECTION_MULTI:
+                return MetricsEvent.ACTION_TEXT_SELECTION_SMART_MULTI;
+            case SelectionEvent.EventType.AUTO_SELECTION:
+                return MetricsEvent.ACTION_TEXT_SELECTION_AUTO;
+            default:
+                return MetricsEvent.VIEW_UNKNOWN;
         }
     }
 
-    private boolean matchesSmartSelectionBounds(SelectionEvent event) {
-        return event.mStart == mSmartIndices[0] && event.mEnd == mSmartIndices[1];
+    private static String getLogTypeString(int logType) {
+        switch (logType) {
+            case MetricsEvent.ACTION_TEXT_SELECTION_OVERTYPE:
+                return "OVERTYPE";
+            case MetricsEvent.ACTION_TEXT_SELECTION_COPY:
+                return "COPY";
+            case MetricsEvent.ACTION_TEXT_SELECTION_PASTE:
+                return "PASTE";
+            case MetricsEvent.ACTION_TEXT_SELECTION_CUT:
+                return "CUT";
+            case MetricsEvent.ACTION_TEXT_SELECTION_SHARE:
+                return "SHARE";
+            case MetricsEvent.ACTION_TEXT_SELECTION_SMART_SHARE:
+                return "SMART_SHARE";
+            case MetricsEvent.ACTION_TEXT_SELECTION_DRAG:
+                return "DRAG";
+            case MetricsEvent.ACTION_TEXT_SELECTION_ABANDON:
+                return "ABANDON";
+            case MetricsEvent.ACTION_TEXT_SELECTION_OTHER:
+                return "OTHER";
+            case MetricsEvent.ACTION_TEXT_SELECTION_SELECT_ALL:
+                return "SELECT_ALL";
+            case MetricsEvent.ACTION_TEXT_SELECTION_RESET:
+                return "RESET";
+            case MetricsEvent.ACTION_TEXT_SELECTION_START:
+                return "SELECTION_STARTED";
+            case MetricsEvent.ACTION_TEXT_SELECTION_MODIFY:
+                return "SELECTION_MODIFIED";
+            case MetricsEvent.ACTION_TEXT_SELECTION_SMART_SINGLE:
+                return "SMART_SELECTION_SINGLE";
+            case MetricsEvent.ACTION_TEXT_SELECTION_SMART_MULTI:
+                return "SMART_SELECTION_MULTI";
+            case MetricsEvent.ACTION_TEXT_SELECTION_AUTO:
+                return "AUTO_SELECTION";
+            default:
+                return UNKNOWN;
+        }
     }
 
-    private boolean containsOriginalSelection(SelectionEvent event) {
-        return event.mStart <= mOrigStart && event.mEnd > mOrigStart;
+    private static int getLogSubType(SelectionEvent event) {
+        switch (event.mEntityType) {
+            case TextClassifier.TYPE_OTHER:
+                return MetricsEvent.TEXT_CLASSIFIER_TYPE_OTHER;
+            case TextClassifier.TYPE_EMAIL:
+                return MetricsEvent.TEXT_CLASSIFIER_TYPE_EMAIL;
+            case TextClassifier.TYPE_PHONE:
+                return MetricsEvent.TEXT_CLASSIFIER_TYPE_PHONE;
+            case TextClassifier.TYPE_ADDRESS:
+                return MetricsEvent.TEXT_CLASSIFIER_TYPE_ADDRESS;
+            case TextClassifier.TYPE_URL:
+                return MetricsEvent.TEXT_CLASSIFIER_TYPE_URL;
+            default:
+                return MetricsEvent.TEXT_CLASSIFIER_TYPE_UNKNOWN;
+        }
+    }
+
+    private static String getLogSubTypeString(int logSubType) {
+        switch (logSubType) {
+            case MetricsEvent.TEXT_CLASSIFIER_TYPE_OTHER:
+                return TextClassifier.TYPE_OTHER;
+            case MetricsEvent.TEXT_CLASSIFIER_TYPE_EMAIL:
+                return TextClassifier.TYPE_EMAIL;
+            case MetricsEvent.TEXT_CLASSIFIER_TYPE_PHONE:
+                return TextClassifier.TYPE_PHONE;
+            case MetricsEvent.TEXT_CLASSIFIER_TYPE_ADDRESS:
+                return TextClassifier.TYPE_ADDRESS;
+            case MetricsEvent.TEXT_CLASSIFIER_TYPE_URL:
+                return TextClassifier.TYPE_URL;
+            default:
+                return TextClassifier.TYPE_UNKNOWN;
+        }
     }
 
     private int getSmartDelta() {
@@ -211,8 +291,9 @@
             return (clamp(mSmartIndices[0] - mOrigStart) << 16)
                     | (clamp(mSmartIndices[1] - mOrigStart) & 0xffff);
         }
-        // If no smart selection, return start selection indices (i.e. [0, 1])
-        return /* (0 << 16) | */ (1 & 0xffff);
+        // If the smart selection model was not run, return invalid selection indices [0,0]. This
+        // allows us to tell from the terminal event alone whether the model was run.
+        return 0;
     }
 
     private int getEventDelta(SelectionEvent event) {
@@ -220,7 +301,7 @@
                 | (clamp(event.mEnd - mOrigStart) & 0xffff);
     }
 
-    private String getTag(SelectionEvent event) {
+    private String getVersionTag(@Nullable SelectionEvent event) {
         final String widgetType;
         switch (mWidgetType) {
             case WidgetType.TEXTVIEW:
@@ -238,7 +319,9 @@
             default:
                 widgetType = UNKNOWN;
         }
-        final String version = Objects.toString(event.mVersionTag, SelectionEvent.NO_VERSION_TAG);
+        final String version = event == null
+                ? SelectionEvent.NO_VERSION_TAG
+                : Objects.toString(event.mVersionTag, SelectionEvent.NO_VERSION_TAG);
         return String.format("%s/%s", widgetType, version);
     }
 
@@ -253,66 +336,17 @@
     private static void debugLog(LogMaker log) {
         if (!DEBUG_LOG_ENABLED) return;
 
+        final String tag = Objects.toString(log.getTaggedData(VERSION_TAG), "tag");
         final int index = Integer.parseInt(Objects.toString(log.getTaggedData(INDEX), ZERO));
-
-        final String event;
-        switch (log.getSubtype()) {
-            case SelectionEvent.ActionType.OVERTYPE:
-                event = "OVERTYPE";
-                break;
-            case SelectionEvent.ActionType.COPY:
-                event = "COPY";
-                break;
-            case SelectionEvent.ActionType.PASTE:
-                event = "PASTE";
-                break;
-            case SelectionEvent.ActionType.CUT:
-                event = "CUT";
-                break;
-            case SelectionEvent.ActionType.SHARE:
-                event = "SHARE";
-                break;
-            case SelectionEvent.ActionType.SMART_SHARE:
-                event = "SMART_SHARE";
-                break;
-            case SelectionEvent.ActionType.DRAG:
-                event = "DRAG";
-                break;
-            case SelectionEvent.ActionType.ABANDON:
-                event = "ABANDON";
-                break;
-            case SelectionEvent.ActionType.OTHER:
-                event = "OTHER";
-                break;
-            case SelectionEvent.ActionType.SELECT_ALL:
-                event = "SELECT_ALL";
-                break;
-            case SelectionEvent.ActionType.RESET:
-                event = "RESET";
-                break;
-            case SelectionEvent.EventType.SELECTION_STARTED:
-                final String tag = Objects.toString(log.getTaggedData(TAG), "tag");
-                String sessionId = Objects.toString(log.getTaggedData(SESSION_ID), "");
-                sessionId = sessionId.substring(sessionId.lastIndexOf("-") + 1);
-                Log.d(LOG_TAG, String.format("New selection session: %s(%s)", tag, sessionId));
-                event = "SELECTION_STARTED";
-                break;
-            case SelectionEvent.EventType.SELECTION_MODIFIED:
-                event = "SELECTION_MODIFIED";
-                break;
-            case SelectionEvent.EventType.SMART_SELECTION_SINGLE:
-                event = "SMART_SELECTION_SINGLE";
-                break;
-            case SelectionEvent.EventType.SMART_SELECTION_MULTI:
-                event = "SMART_SELECTION_MULTI";
-                break;
-            case SelectionEvent.EventType.AUTO_SELECTION:
-                event = "AUTO_SELECTION";
-                break;
-            default:
-                event = "UNKNOWN";
+        if (log.getType() == MetricsEvent.ACTION_TEXT_SELECTION_START) {
+            String sessionId = Objects.toString(log.getTaggedData(SESSION_ID), "");
+            sessionId = sessionId.substring(sessionId.lastIndexOf("-") + 1);
+            Log.d(LOG_TAG, String.format("New selection session: %s(%s)", tag, sessionId));
         }
 
+        final String type = getLogTypeString(log.getType());
+        final String subType = getLogSubTypeString(log.getSubtype());
+
         final int smartIndices = Integer.parseInt(
                 Objects.toString(log.getTaggedData(SMART_INDICES), ZERO));
         final int smartStart = (short) ((smartIndices & 0xffff0000) >> 16);
@@ -323,11 +357,8 @@
         final int eventStart = (short) ((eventIndices & 0xffff0000) >> 16);
         final int eventEnd = (short) (eventIndices & 0xffff);
 
-        final String entity = Objects.toString(
-                log.getTaggedData(ENTITY_TYPE), TextClassifier.TYPE_UNKNOWN);
-
-        Log.d(LOG_TAG, String.format("%2d: %s, context=%d,%d - old=%d,%d [%s]",
-                index, event, eventStart, eventEnd, smartStart, smartEnd, entity));
+        Log.d(LOG_TAG, String.format("%2d: %s/%s, context=%d,%d - old=%d,%d (%s)",
+                index, type, subType, eventStart, eventEnd, smartStart, smartEnd, tag));
     }
 
     /**
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index f918cad..637b60e 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2723,25 +2723,20 @@
      *   {@code IFRAME}, in which case it would be treated the same way as multiple forms described
      *   above, except that the {@link ViewStructure#setWebDomain(String) web domain} of the
      *   {@code FORM} contains the {@code src} attribute from the {@code IFRAME} node.
-     *   <li>If the Android SDK provides a similar View, then should be set with the
-     *   fully-qualified class name of such view.
      *   <li>The W3C autofill field ({@code autocomplete} tag attribute) maps to
-     *       {@link ViewStructure#setAutofillHints(String[])}.
-     *   <li>The {@code type} attribute of {@code INPUT} tags maps to
-     *       {@link ViewStructure#setInputType(int)}.
-     *   <li>The {@code value} attribute of {@code INPUT} tags maps to
-     *       {@link ViewStructure#setText(CharSequence)}.
-     *   <li>If the view is editalbe, the {@link ViewStructure#setAutofillType(int)} and
+     *   {@link ViewStructure#setAutofillHints(String[])}.
+     *   <li>If the view is editable, the {@link ViewStructure#setAutofillType(int)} and
      *   {@link ViewStructure#setAutofillValue(AutofillValue)} must be set.
      *   <li>The {@code placeholder} attribute maps to {@link ViewStructure#setHint(CharSequence)}.
      *   <li>Other HTML attributes can be represented through
      *   {@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}.
      * </ol>
      *
-     * <p>It should also call {@code structure.setDataIsSensitive(false)} for fields whose value
-     * were not dynamically changed (for example, through Javascript).
+     * <p>If the WebView implementation can determine that the value of a field was set statically
+     * (for example, not through Javascript), it should also call
+     * {@code structure.setDataIsSensitive(false)}.
      *
-     * <p>Example1: an HTML form with 2 fields for username and password.
+     * <p>For example, an HTML form with 2 fields for username and password:
      *
      * <pre class="prettyprint">
      *    &lt;input type="text" name="username" id="user" value="Type your username" autocomplete="username" placeholder="Email or username"&gt;
@@ -2754,51 +2749,27 @@
      *     int index = structure.addChildCount(2);
      *     ViewStructure username = structure.newChild(index);
      *     username.setAutofillId(structure.getAutofillId(), 1); // id 1 - first child
-     *     username.setClassName("input");
-     *     username.setInputType("android.widget.EditText");
      *     username.setAutofillHints("username");
      *     username.setHtmlInfo(username.newHtmlInfoBuilder("input")
      *         .addAttribute("type", "text")
      *         .addAttribute("name", "username")
-     *         .addAttribute("id", "user")
      *         .build());
      *     username.setHint("Email or username");
      *     username.setAutofillType(View.AUTOFILL_TYPE_TEXT);
      *     username.setAutofillValue(AutofillValue.forText("Type your username"));
-     *     username.setText("Type your username");
-     *     // Value of the field is not sensitive because it was not dynamically changed:
+     *     // Value of the field is not sensitive because it was created statically and not changed.
      *     username.setDataIsSensitive(false);
      *
      *     ViewStructure password = structure.newChild(index + 1);
      *     username.setAutofillId(structure, 2); // id 2 - second child
-     *     password.setInputType("android.widget.EditText");
-     *     password.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
      *     password.setAutofillHints("current-password");
      *     password.setHtmlInfo(password.newHtmlInfoBuilder("input")
      *         .addAttribute("type", "password")
      *         .addAttribute("name", "password")
-     *         .addAttribute("id", "pass")
      *         .build());
      *     password.setHint("Password");
      *     password.setAutofillType(View.AUTOFILL_TYPE_TEXT);
      * </pre>
-     *
-     * <p>Example2: an IFRAME tag.
-     *
-     * <pre class="prettyprint">
-     *    &lt;iframe src="https://example.com/login"/&gt;
-     * </pre>
-     *
-     * <p>Would map to:
-     *
-     * <pre class="prettyprint">
-     *     int index = structure.addChildCount(1);
-     *     ViewStructure iframe = structure.newChildFor(index);
-     *     iframe.setAutofillId(structure.getAutofillId(), 1);
-     *     iframe.setHtmlInfo(iframe.newHtmlInfoBuilder("iframe")
-     *         .addAttribute("src", "https://example.com/login")
-     *         .build());
-     * </pre>
      */
     @Override
     public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index e7e539c..cbe75c4 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -154,6 +154,10 @@
      * other than the UI thread so clients should exercise caution
      * when accessing private data or the view system.
      *
+     * <p>Note: when Safe Browsing is enabled, these URLs still undergo Safe Browsing checks. If
+     * this is undesired, whitelist the URL with {@link WebView#setSafeBrowsingWhitelist} or ignore
+     * the warning with {@link #onSafeBrowsingHit}.
+     *
      * @param view The {@link android.webkit.WebView} that is requesting the
      *             resource.
      * @param url The raw url of the resource.
@@ -177,6 +181,10 @@
      * other than the UI thread so clients should exercise caution
      * when accessing private data or the view system.
      *
+     * <p>Note: when Safe Browsing is enabled, these URLs still undergo Safe Browsing checks. If
+     * this is undesired, whitelist the URL with {@link WebView#setSafeBrowsingWhitelist} or ignore
+     * the warning with {@link #onSafeBrowsingHit}.
+     *
      * @param view The {@link android.webkit.WebView} that is requesting the
      *             resource.
      * @param request Object containing the details of the request.
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index 60b4757..e40023d 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -22,11 +22,10 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
+import android.icu.text.DateFormat;
 import android.icu.text.DisplayContext;
-import android.icu.text.SimpleDateFormat;
 import android.icu.util.Calendar;
 import android.os.Parcelable;
-import android.text.format.DateFormat;
 import android.util.AttributeSet;
 import android.util.StateSet;
 import android.view.HapticFeedbackConstants;
@@ -62,8 +61,8 @@
     private static final int[] ATTRS_DISABLED_ALPHA = new int[] {
             com.android.internal.R.attr.disabledAlpha};
 
-    private SimpleDateFormat mYearFormat;
-    private SimpleDateFormat mMonthDayFormat;
+    private DateFormat mYearFormat;
+    private DateFormat mMonthDayFormat;
 
     // Top-level container.
     private ViewGroup mContainer;
@@ -273,19 +272,16 @@
     /**
      * Listener called when the user clicks on a header item.
      */
-    private final OnClickListener mOnHeaderClickListener = new OnClickListener() {
-        @Override
-        public void onClick(View v) {
-            tryVibrate();
+    private final OnClickListener mOnHeaderClickListener = v -> {
+        tryVibrate();
 
-            switch (v.getId()) {
-                case R.id.date_picker_header_year:
-                    setCurrentView(VIEW_YEAR);
-                    break;
-                case R.id.date_picker_header_date:
-                    setCurrentView(VIEW_MONTH_DAY);
-                    break;
-            }
+        switch (v.getId()) {
+            case R.id.date_picker_header_year:
+                setCurrentView(VIEW_YEAR);
+                break;
+            case R.id.date_picker_header_date:
+                setCurrentView(VIEW_MONTH_DAY);
+                break;
         }
     };
 
@@ -299,10 +295,9 @@
         }
 
         // Update the date formatter.
-        final String datePattern = DateFormat.getBestDateTimePattern(locale, "EMMMd");
-        mMonthDayFormat = new SimpleDateFormat(datePattern, locale);
+        mMonthDayFormat = DateFormat.getInstanceForSkeleton("EMMMd", locale);
         mMonthDayFormat.setContext(DisplayContext.CAPITALIZATION_FOR_STANDALONE);
-        mYearFormat = new SimpleDateFormat("y", locale);
+        mYearFormat = DateFormat.getInstanceForSkeleton("y", locale);
 
         // Update the header text.
         onCurrentDateChanged(false);
@@ -344,14 +339,11 @@
             case VIEW_YEAR:
                 final int year = mCurrentDate.get(Calendar.YEAR);
                 mYearPickerView.setYear(year);
-                mYearPickerView.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        mYearPickerView.requestFocus();
-                        final View selected = mYearPickerView.getSelectedView();
-                        if (selected != null) {
-                            selected.requestFocus();
-                        }
+                mYearPickerView.post(() -> {
+                    mYearPickerView.requestFocus();
+                    final View selected = mYearPickerView.getSelectedView();
+                    if (selected != null) {
+                        selected.requestFocus();
                     }
                 });
 
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 31d878f..92e8f44 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -41,6 +41,7 @@
 import android.graphics.RectF;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.metrics.LogMaker;
 import android.os.Bundle;
 import android.os.LocaleList;
 import android.os.Parcel;
@@ -1250,7 +1251,8 @@
         }
     }
 
-    void sendOnTextChanged(int start, int after) {
+    void sendOnTextChanged(int start, int before, int after) {
+        getSelectionActionModeHelper().onTextChanged(start, start + before);
         updateSpellCheckSpans(start, start + after, false);
 
         // Flip flag to indicate the word iterator needs to have the text reset.
@@ -3920,6 +3922,10 @@
                         textClassification.getLabel())
                         .setIcon(textClassification.getIcon())
                         .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+                mMetricsLogger.write(
+                        new LogMaker(MetricsEvent.TEXT_SELECTION_MENU_ITEM_ASSIST)
+                                .setType(MetricsEvent.TYPE_OPEN)
+                                .setSubtype(textClassification.getLogType()));
             }
         }
 
@@ -3961,6 +3967,9 @@
                                 .onClick(mTextView);
                     }
                 }
+                mMetricsLogger.action(
+                        MetricsEvent.ACTION_TEXT_SELECTION_MENU_ITEM_ASSIST,
+                        textClassification.getLogType());
                 stopTextActionMode();
                 return true;
             }
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 1285c10..4ebb3cf 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -20,7 +20,6 @@
 import android.annotation.Nullable;
 import android.annotation.UiThread;
 import android.annotation.WorkerThread;
-import android.content.Context;
 import android.os.AsyncTask;
 import android.os.LocaleList;
 import android.text.Selection;
@@ -41,6 +40,7 @@
 import java.util.Objects;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
+import java.util.regex.Pattern;
 
 /**
  * Helper class for starting selection action mode
@@ -70,8 +70,7 @@
         mTextClassificationHelper = new TextClassificationHelper(
                 mTextView.getTextClassifier(), mTextView.getText(),
                 0, 1, mTextView.getTextLocales());
-        mSelectionTracker =
-                new SelectionTracker(mTextView.getContext(), mTextView.isTextEditable());
+        mSelectionTracker = new SelectionTracker(mTextView);
     }
 
     public void startActionModeAsync(boolean adjustSelection) {
@@ -123,10 +122,8 @@
                 SelectionEvent.ActionType.DRAG, mTextClassification);
     }
 
-    public void onTypeOverSelection() {
-        mSelectionTracker.onSelectionAction(
-                mTextView.getSelectionStart(), mTextView.getSelectionEnd(),
-                SelectionEvent.ActionType.OVERTYPE, mTextClassification);
+    public void onTextChanged(int start, int end) {
+        mSelectionTracker.onTextChanged(start, end, mTextClassification);
     }
 
     public boolean resetSelection(int textIndex) {
@@ -211,19 +208,18 @@
      */
     private static final class SelectionTracker {
 
-        private final Context mContext;
+        private final TextView mTextView;
         private SelectionMetricsLogger mLogger;
 
         private int mOriginalStart;
         private int mOriginalEnd;
         private int mSelectionStart;
         private int mSelectionEnd;
-        private boolean mSelectionStarted;
         private boolean mAllowReset;
 
-        SelectionTracker(Context context, boolean editable) {
-            mContext = Preconditions.checkNotNull(context);
-            mLogger = new SelectionMetricsLogger(context, editable);
+        SelectionTracker(TextView textView) {
+            mTextView = Preconditions.checkNotNull(textView);
+            mLogger = new SelectionMetricsLogger(textView);
         }
 
         /**
@@ -231,11 +227,10 @@
          */
         public void onOriginalSelection(
                 CharSequence text, int selectionStart, int selectionEnd, boolean editableText) {
-            mOriginalStart = selectionStart;
-            mOriginalEnd = selectionEnd;
-            mSelectionStarted = true;
+            mOriginalStart = mSelectionStart = selectionStart;
+            mOriginalEnd = mSelectionEnd = selectionEnd;
             mAllowReset = false;
-            maybeInvalidateLogger(editableText);
+            maybeInvalidateLogger();
             mLogger.logSelectionStarted(text, selectionStart);
         }
 
@@ -243,7 +238,7 @@
          * Called when selection action mode is started and the results come from a classifier.
          */
         public void onSmartSelection(SelectionResult result) {
-            if (mSelectionStarted) {
+            if (isSelectionStarted()) {
                 mSelectionStart = result.mStart;
                 mSelectionEnd = result.mEnd;
                 mAllowReset = mSelectionStart != mOriginalStart || mSelectionEnd != mOriginalEnd;
@@ -258,7 +253,9 @@
         public void onSelectionUpdated(
                 int selectionStart, int selectionEnd,
                 @Nullable TextClassification classification) {
-            if (mSelectionStarted) {
+            if (isSelectionStarted()) {
+                mSelectionStart = selectionStart;
+                mSelectionEnd = selectionEnd;
                 mAllowReset = false;
                 mLogger.logSelectionModified(selectionStart, selectionEnd, classification, null);
             }
@@ -269,10 +266,13 @@
          */
         public void onSelectionDestroyed() {
             mAllowReset = false;
-            mSelectionStarted = false;
-            mLogger.logSelectionAction(
-                    mSelectionStart, mSelectionEnd,
-                    SelectionEvent.ActionType.ABANDON, null /* classification */);
+            // Wait a few ms to see if the selection was destroyed because of a text change event.
+            mTextView.postDelayed(() -> {
+                mLogger.logSelectionAction(
+                        mSelectionStart, mSelectionEnd,
+                        SelectionEvent.ActionType.ABANDON, null /* classification */);
+                mSelectionStart = mSelectionEnd = -1;
+            }, 100 /* ms */);
         }
 
         /**
@@ -282,7 +282,7 @@
                 int selectionStart, int selectionEnd,
                 @SelectionEvent.ActionType int action,
                 @Nullable TextClassification classification) {
-            if (mSelectionStarted) {
+            if (isSelectionStarted()) {
                 mAllowReset = false;
                 mLogger.logSelectionAction(selectionStart, selectionEnd, action, classification);
             }
@@ -296,13 +296,15 @@
          */
         public boolean resetSelection(int textIndex, Editor editor) {
             final TextView textView = editor.getTextView();
-            if (mSelectionStarted
+            if (isSelectionStarted()
                     && mAllowReset
                     && textIndex >= mSelectionStart && textIndex <= mSelectionEnd
                     && textView.getText() instanceof Spannable) {
                 mAllowReset = false;
                 boolean selected = editor.selectCurrentWord();
                 if (selected) {
+                    mSelectionStart = editor.getTextView().getSelectionStart();
+                    mSelectionEnd = editor.getTextView().getSelectionEnd();
                     mLogger.logSelectionAction(
                             textView.getSelectionStart(), textView.getSelectionEnd(),
                             SelectionEvent.ActionType.RESET, null /* classification */);
@@ -312,11 +314,21 @@
             return false;
         }
 
-        private void maybeInvalidateLogger(boolean editableText) {
-            if (mLogger.isEditTextLogger() != editableText) {
-                mLogger = new SelectionMetricsLogger(mContext, editableText);
+        public void onTextChanged(int start, int end, TextClassification classification) {
+            if (isSelectionStarted() && start == mSelectionStart && end == mSelectionEnd) {
+                onSelectionAction(start, end, SelectionEvent.ActionType.OVERTYPE, classification);
             }
         }
+
+        private void maybeInvalidateLogger() {
+            if (mLogger.isEditTextLogger() != mTextView.isTextEditable()) {
+                mLogger = new SelectionMetricsLogger(mTextView);
+            }
+        }
+
+        private boolean isSelectionStarted() {
+            return mSelectionStart >= 0 && mSelectionEnd >= 0 && mSelectionStart != mSelectionEnd;
+        }
     }
 
     // TODO: Write tests
@@ -336,20 +348,22 @@
     private static final class SelectionMetricsLogger {
 
         private static final String LOG_TAG = "SelectionMetricsLogger";
+        private static final Pattern PATTERN_WHITESPACE = Pattern.compile("\\s+");
 
         private final SmartSelectionEventTracker mDelegate;
         private final boolean mEditTextLogger;
-        private final BreakIterator mWordIterator = BreakIterator.getWordInstance();
+        private final BreakIterator mWordIterator;
         private int mStartIndex;
-        private int mEndIndex;
         private String mText;
 
-        SelectionMetricsLogger(Context context, boolean editable) {
-            final @SmartSelectionEventTracker.WidgetType int widgetType = editable
+        SelectionMetricsLogger(TextView textView) {
+            Preconditions.checkNotNull(textView);
+            final @SmartSelectionEventTracker.WidgetType int widgetType = textView.isTextEditable()
                     ? SmartSelectionEventTracker.WidgetType.EDITTEXT
                     : SmartSelectionEventTracker.WidgetType.TEXTVIEW;
-            mDelegate = new SmartSelectionEventTracker(context, widgetType);
-            mEditTextLogger = editable;
+            mDelegate = new SmartSelectionEventTracker(textView.getContext(), widgetType);
+            mEditTextLogger = textView.isTextEditable();
+            mWordIterator = BreakIterator.getWordInstance(textView.getTextLocale());
         }
 
         public void logSelectionStarted(CharSequence text, int index) {
@@ -361,7 +375,6 @@
                 }
                 mWordIterator.setText(mText);
                 mStartIndex = index;
-                mEndIndex = mWordIterator.following(index);
                 mDelegate.logEvent(SelectionEvent.selectionStarted(0));
             } catch (Exception e) {
                 // Avoid crashes due to logging.
@@ -424,12 +437,15 @@
             } else if (start < mStartIndex) {
                 wordIndices[0] = -countWordsForward(start);
             } else {  // start > mStartIndex
-                if (mStartIndex < start && start < mEndIndex) {
-                    // If the new selection did not move past the original word,
-                    // assume it has not moved.
-                    wordIndices[0] = 0;
-                } else {
-                    wordIndices[0] = countWordsBackward(start);
+                wordIndices[0] = countWordsBackward(start);
+
+                // For the selection start index, avoid counting a partial word backwards.
+                if (!mWordIterator.isBoundary(start)
+                        && !isWhitespace(
+                                mWordIterator.preceding(start),
+                                mWordIterator.following(start))) {
+                    // We counted a partial word. Remove it.
+                    wordIndices[0]--;
                 }
             }
 
@@ -473,7 +489,7 @@
         }
 
         private boolean isWhitespace(int start, int end) {
-            return mText.substring(start, end).trim().isEmpty();
+            return PATTERN_WHITESPACE.matcher(mText.substring(start, end)).matches();
         }
     }
 
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index 8de17c0..8696d0d 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -146,12 +146,17 @@
         // and relays them to the tab content.
         mTabKeyListener = new OnKeyListener() {
             public boolean onKey(View v, int keyCode, KeyEvent event) {
+                if (KeyEvent.isModifierKey(keyCode)) {
+                    return false;
+                }
                 switch (keyCode) {
                     case KeyEvent.KEYCODE_DPAD_CENTER:
                     case KeyEvent.KEYCODE_DPAD_LEFT:
                     case KeyEvent.KEYCODE_DPAD_RIGHT:
                     case KeyEvent.KEYCODE_DPAD_UP:
                     case KeyEvent.KEYCODE_DPAD_DOWN:
+                    case KeyEvent.KEYCODE_TAB:
+                    case KeyEvent.KEYCODE_SPACE:
                     case KeyEvent.KEYCODE_ENTER:
                         return false;
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b2e2e88..9826fa0 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8409,7 +8409,8 @@
 
         if (mMaxMode != LINES) {
             desired = Math.min(desired, mMaximum);
-        } else if (cap && linecount > mMaximum && layout instanceof DynamicLayout) {
+        } else if (cap && linecount > mMaximum && (layout instanceof DynamicLayout
+                || layout instanceof BoringLayout)) {
             desired = layout.getLineTop(mMaximum);
 
             if (dr != null) {
@@ -9364,7 +9365,7 @@
             }
         }
 
-        if (mEditor != null) mEditor.sendOnTextChanged(start, after);
+        if (mEditor != null) mEditor.sendOnTextChanged(start, before, after);
     }
 
     /**
@@ -10875,6 +10876,7 @@
     @Override
     public boolean performLongClick() {
         boolean handled = false;
+        boolean performedHapticFeedback = false;
 
         if (mEditor != null) {
             mEditor.mIsBeingLongClicked = true;
@@ -10882,6 +10884,7 @@
 
         if (super.performLongClick()) {
             handled = true;
+            performedHapticFeedback = true;
         }
 
         if (mEditor != null) {
@@ -10890,7 +10893,9 @@
         }
 
         if (handled) {
-            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+            if (!performedHapticFeedback) {
+              performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+            }
             if (mEditor != null) mEditor.mDiscardNextActionUp = true;
         } else {
             MetricsLogger.action(
diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java
index 36ab394..b22ce5e 100644
--- a/core/java/com/android/internal/app/PlatLogoActivity.java
+++ b/core/java/com/android/internal/app/PlatLogoActivity.java
@@ -53,8 +53,7 @@
 import android.widget.ImageView;
 
 public class PlatLogoActivity extends Activity {
-    public static final boolean REVEAL_THE_NAME = false;
-    public static final boolean FINISH = false;
+    public static final boolean FINISH = true;
 
     FrameLayout mLayout;
     int mTapCount;
@@ -85,15 +84,18 @@
         im.setAlpha(0f);
 
         im.setBackground(new RippleDrawable(
-                ColorStateList.valueOf(0xFFFFFFFF),
+                ColorStateList.valueOf(0xFF776677),
                 getDrawable(com.android.internal.R.drawable.platlogo),
                 null));
-//        im.setOutlineProvider(new ViewOutlineProvider() {
-//            @Override
-//            public void getOutline(View view, Outline outline) {
-//                outline.setOval(0, 0, view.getWidth(), view.getHeight());
-//            }
-//        });
+        im.setOutlineProvider(new ViewOutlineProvider() {
+            @Override
+            public void getOutline(View view, Outline outline) {
+                final int w = view.getWidth();
+                final int h = view.getHeight();
+                outline.setOval((int)(w*.125), (int)(h*.125), (int)(w*.96), (int)(h*.96));
+            }
+        });
+        im.setElevation(12f*dp);
         im.setClickable(true);
         im.setOnClickListener(new View.OnClickListener() {
             @Override
@@ -103,18 +105,6 @@
                     public boolean onLongClick(View v) {
                         if (mTapCount < 5) return false;
 
-                        if (REVEAL_THE_NAME) {
-                            final Drawable overlay = getDrawable(
-                                com.android.internal.R.drawable.platlogo_m);
-                            overlay.setBounds(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
-                            im.getOverlay().clear();
-                            im.getOverlay().add(overlay);
-                            overlay.setAlpha(0);
-                            ObjectAnimator.ofInt(overlay, "alpha", 0, 255)
-                                .setDuration(500)
-                                .start();
-                        }
-
                         final ContentResolver cr = getContentResolver();
                         if (Settings.System.getLong(cr, Settings.System.EGG_MODE, 0)
                                 == 0) {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index d20345b..4300b18 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -119,7 +119,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 165 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 166 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS;
@@ -183,6 +183,13 @@
         return mKernelMemoryStats;
     }
 
+    /** Container for Resource Power Manager stats. Updated by updateRpmStatsLocked. */
+    private final RpmStats mTmpRpmStats = new RpmStats();
+    /** The soonest the RPM stats can be updated after it was last updated. */
+    private static final long RPM_STATS_UPDATE_FREQ_MS = 1000;
+    /** Last time that RPM stats were updated by updateRpmStatsLocked. */
+    private long mLastRpmStatsUpdateTimeMs = -RPM_STATS_UPDATE_FREQ_MS;
+
     public interface BatteryCallback {
         public void batteryNeedsCpuUpdate();
         public void batteryPowerChanged(boolean onBattery);
@@ -190,6 +197,7 @@
     }
 
     public interface PlatformIdleStateCallback {
+        public void fillLowPowerStats(RpmStats rpmStats);
         public String getPlatformLowPowerStats();
         public String getSubsystemLowPowerStats();
     }
@@ -265,7 +273,8 @@
         int UPDATE_WIFI = 0x02;
         int UPDATE_RADIO = 0x04;
         int UPDATE_BT = 0x08;
-        int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT;
+        int UPDATE_RPM = 0x10; // 16
+        int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM;
 
         Future<?> scheduleSync(String reason, int flags);
         Future<?> scheduleCpuSyncDueToRemovedUid(int uid);
@@ -609,6 +618,25 @@
     private PowerProfile mPowerProfile;
 
     /*
+     * Holds a SamplingTimer associated with each Resource Power Manager state and voter,
+     * recording their times when on-battery (regardless of screen state).
+     */
+    private final HashMap<String, SamplingTimer> mRpmStats = new HashMap<>();
+    /** Times for each Resource Power Manager state and voter when screen-off and on-battery. */
+    private final HashMap<String, SamplingTimer> mScreenOffRpmStats = new HashMap<>();
+
+    @Override
+    public Map<String, ? extends Timer> getRpmStats() {
+        return mRpmStats;
+    }
+
+    // TODO: Note: screenOffRpmStats has been disabled via SCREEN_OFF_RPM_STATS_ENABLED.
+    @Override
+    public Map<String, ? extends Timer> getScreenOffRpmStats() {
+        return mScreenOffRpmStats;
+    }
+
+    /*
      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
      */
     private final HashMap<String, SamplingTimer> mKernelWakelockStats = new HashMap<>();
@@ -2628,6 +2656,26 @@
         }
     }
 
+    /** Get Resource Power Manager stats. Create a new one if it doesn't already exist. */
+    public SamplingTimer getRpmTimerLocked(String name) {
+        SamplingTimer rpmt = mRpmStats.get(name);
+        if (rpmt == null) {
+            rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase);
+            mRpmStats.put(name, rpmt);
+        }
+        return rpmt;
+    }
+
+    /** Get Screen-off Resource Power Manager stats. Create new one if it doesn't already exist. */
+    public SamplingTimer getScreenOffRpmTimerLocked(String name) {
+        SamplingTimer rpmt = mScreenOffRpmStats.get(name);
+        if (rpmt == null) {
+            rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase);
+            mScreenOffRpmStats.put(name, rpmt);
+        }
+        return rpmt;
+    }
+
     /*
      * Get the wakeup reason counter, and create a new one if one
      * doesn't already exist.
@@ -3516,6 +3564,12 @@
                 updateKernelWakelocksLocked();
                 updateBatteryPropertiesLocked();
             }
+            // This if{} is only necessary due to SCREEN_OFF_RPM_STATS_ENABLED, which exists because
+            // updateRpmStatsLocked is too slow to run each screen change. When the speed is
+            // improved, remove the surrounding if{}.
+            if (SCREEN_OFF_RPM_STATS_ENABLED || updateOnBatteryTimeBase) {
+                updateRpmStatsLocked(); // if either OnBattery or OnBatteryScreenOff timebase changes.
+            }
             if (DEBUG_ENERGY_CPU) {
                 Slog.d(TAG, "Updating cpu time because screen is now " + (screenOff ? "off" : "on")
                         + " and battery is " + (unplugged ? "on" : "off"));
@@ -9481,6 +9535,19 @@
             }
         }
 
+        if (mRpmStats.size() > 0) {
+            for (SamplingTimer timer : mRpmStats.values()) {
+                mOnBatteryTimeBase.remove(timer);
+            }
+            mRpmStats.clear();
+        }
+        if (mScreenOffRpmStats.size() > 0) {
+            for (SamplingTimer timer : mScreenOffRpmStats.values()) {
+                mOnBatteryScreenOffTimeBase.remove(timer);
+            }
+            mScreenOffRpmStats.clear();
+        }
+
         if (mKernelWakelockStats.size() > 0) {
             for (SamplingTimer timer : mKernelWakelockStats.values()) {
                 mOnBatteryScreenOffTimeBase.remove(timer);
@@ -10183,6 +10250,61 @@
     }
 
     /**
+     * Read and record Resource Power Manager (RPM) state and voter times.
+     * If RPM stats were fetched more recently than RPM_STATS_UPDATE_FREQ_MS ago, uses the old data
+     * instead of fetching it anew.
+     */
+    public void updateRpmStatsLocked() {
+        if (mPlatformIdleStateCallback == null) return;
+        long now = SystemClock.elapsedRealtime();
+        if (now - mLastRpmStatsUpdateTimeMs >= RPM_STATS_UPDATE_FREQ_MS) {
+            mPlatformIdleStateCallback.fillLowPowerStats(mTmpRpmStats);
+            mLastRpmStatsUpdateTimeMs = now;
+        }
+
+        for (Map.Entry<String, RpmStats.PowerStatePlatformSleepState> pstate
+                : mTmpRpmStats.mPlatformLowPowerStats.entrySet()) {
+
+            // Update values for this platform state.
+            final String pName = pstate.getKey();
+            final long pTimeUs = pstate.getValue().mTimeMs * 1000;
+            final int pCount = pstate.getValue().mCount;
+            getRpmTimerLocked(pName).update(pTimeUs, pCount);
+            if (SCREEN_OFF_RPM_STATS_ENABLED) {
+                getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount);
+            }
+
+            // Update values for each voter of this platform state.
+            for (Map.Entry<String, RpmStats.PowerStateElement> voter
+                    : pstate.getValue().mVoters.entrySet()) {
+                final String vName = pName + "." + voter.getKey();
+                final long vTimeUs = voter.getValue().mTimeMs * 1000;
+                final int vCount = voter.getValue().mCount;
+                getRpmTimerLocked(vName).update(vTimeUs, vCount);
+                if (SCREEN_OFF_RPM_STATS_ENABLED) {
+                    getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount);
+                }
+            }
+        }
+
+        for (Map.Entry<String, RpmStats.PowerStateSubsystem> subsys
+                : mTmpRpmStats.mSubsystemLowPowerStats.entrySet()) {
+
+            final String subsysName = subsys.getKey();
+            for (Map.Entry<String, RpmStats.PowerStateElement> sstate
+                    : subsys.getValue().mStates.entrySet()) {
+                final String name = subsysName + "." + sstate.getKey();
+                final long timeUs = sstate.getValue().mTimeMs * 1000;
+                final int count = sstate.getValue().mCount;
+                getRpmTimerLocked(name).update(timeUs, count);
+                if (SCREEN_OFF_RPM_STATS_ENABLED) {
+                    getScreenOffRpmTimerLocked(name).update(timeUs, count);
+                }
+            }
+        }
+    }
+
+    /**
      * Read and distribute kernel wake lock use across apps.
      */
     public void updateKernelWakelocksLocked() {
@@ -11627,6 +11749,27 @@
         mBluetoothScanNesting = 0;
         mBluetoothScanTimer.readSummaryFromParcelLocked(in);
 
+        int NRPMS = in.readInt();
+        if (NRPMS > 10000) {
+            throw new ParcelFormatException("File corrupt: too many rpm stats " + NRPMS);
+        }
+        for (int irpm = 0; irpm < NRPMS; irpm++) {
+            if (in.readInt() != 0) {
+                String rpmName = in.readString();
+                getRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
+            }
+        }
+        int NSORPMS = in.readInt();
+        if (NSORPMS > 10000) {
+            throw new ParcelFormatException("File corrupt: too many screen-off rpm stats " + NSORPMS);
+        }
+        for (int irpm = 0; irpm < NSORPMS; irpm++) {
+            if (in.readInt() != 0) {
+                String rpmName = in.readString();
+                getScreenOffRpmTimerLocked(rpmName).readSummaryFromParcelLocked(in);
+            }
+        }
+
         int NKW = in.readInt();
         if (NKW > 10000) {
             throw new ParcelFormatException("File corrupt: too many kernel wake locks " + NKW);
@@ -12015,6 +12158,29 @@
         mCameraOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
 
+        out.writeInt(mRpmStats.size());
+        for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
+            Timer rpmt = ent.getValue();
+            if (rpmt != null) {
+                out.writeInt(1);
+                out.writeString(ent.getKey());
+                rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+            } else {
+                out.writeInt(0);
+            }
+        }
+        out.writeInt(mScreenOffRpmStats.size());
+        for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
+            Timer rpmt = ent.getValue();
+            if (rpmt != null) {
+                out.writeInt(1);
+                out.writeString(ent.getKey());
+                rpmt.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+            } else {
+                out.writeInt(0);
+            }
+        }
+
         out.writeInt(mKernelWakelockStats.size());
         for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
             Timer kwlt = ent.getValue();
@@ -12474,6 +12640,25 @@
         mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
         mLastWriteTime = in.readLong();
 
+        mRpmStats.clear();
+        int NRPMS = in.readInt();
+        for (int irpm = 0; irpm < NRPMS; irpm++) {
+            if (in.readInt() != 0) {
+                String rpmName = in.readString();
+                SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryTimeBase, in);
+                mRpmStats.put(rpmName, rpmt);
+            }
+        }
+        mScreenOffRpmStats.clear();
+        int NSORPMS = in.readInt();
+        for (int irpm = 0; irpm < NSORPMS; irpm++) {
+            if (in.readInt() != 0) {
+                String rpmName = in.readString();
+                SamplingTimer rpmt = new SamplingTimer(mClocks, mOnBatteryScreenOffTimeBase, in);
+                mScreenOffRpmStats.put(rpmName, rpmt);
+            }
+        }
+
         mKernelWakelockStats.clear();
         int NKW = in.readInt();
         for (int ikw = 0; ikw < NKW; ikw++) {
@@ -12639,6 +12824,29 @@
         mDischargeScreenOffCounter.writeToParcel(out);
         out.writeLong(mLastWriteTime);
 
+        out.writeInt(mRpmStats.size());
+        for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) {
+            SamplingTimer rpmt = ent.getValue();
+            if (rpmt != null) {
+                out.writeInt(1);
+                out.writeString(ent.getKey());
+                rpmt.writeToParcel(out, uSecRealtime);
+            } else {
+                out.writeInt(0);
+            }
+        }
+        out.writeInt(mScreenOffRpmStats.size());
+        for (Map.Entry<String, SamplingTimer> ent : mScreenOffRpmStats.entrySet()) {
+            SamplingTimer rpmt = ent.getValue();
+            if (rpmt != null) {
+                out.writeInt(1);
+                out.writeString(ent.getKey());
+                rpmt.writeToParcel(out, uSecRealtime);
+            } else {
+                out.writeInt(0);
+            }
+        }
+
         if (inclUids) {
             out.writeInt(mKernelWakelockStats.size());
             for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
@@ -12663,6 +12871,7 @@
                 }
             }
         } else {
+            // TODO: There should be two 0's printed here, not just one.
             out.writeInt(0);
         }
 
diff --git a/core/java/com/android/internal/os/ClassLoaderFactory.java b/core/java/com/android/internal/os/ClassLoaderFactory.java
index b2b769e..387857f 100644
--- a/core/java/com/android/internal/os/ClassLoaderFactory.java
+++ b/core/java/com/android/internal/os/ClassLoaderFactory.java
@@ -88,12 +88,20 @@
         final ClassLoader classLoader = createClassLoader(dexPath, librarySearchPath, parent,
                 classloaderName);
 
+        boolean isForVendor = false;
+        for (String path : dexPath.split(":")) {
+            if (path.startsWith("/vendor/")) {
+                isForVendor = true;
+                break;
+            }
+        }
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "createClassloaderNamespace");
         String errorMessage = createClassloaderNamespace(classLoader,
                                                          targetSdkVersion,
                                                          librarySearchPath,
                                                          libraryPermittedPath,
-                                                         isNamespaceShared);
+                                                         isNamespaceShared,
+                                                         isForVendor);
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
 
         if (errorMessage != null) {
@@ -108,5 +116,6 @@
                                                             int targetSdkVersion,
                                                             String librarySearchPath,
                                                             String libraryPermittedPath,
-                                                            boolean isNamespaceShared);
+                                                            boolean isNamespaceShared,
+                                                            boolean isForVendor);
 }
diff --git a/core/java/com/android/internal/os/RpmStats.java b/core/java/com/android/internal/os/RpmStats.java
new file mode 100644
index 0000000..befc76e
--- /dev/null
+++ b/core/java/com/android/internal/os/RpmStats.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.os;
+
+import android.util.ArrayMap;
+
+import java.util.Map;
+
+/**
+ * Container for Resource Power Manager states and their data.
+ * Values can be populated by the BatteryStatsService.fillLowPowerStats jni function.
+ */
+public final class RpmStats {
+    public Map<String, PowerStatePlatformSleepState> mPlatformLowPowerStats = new ArrayMap<>();
+    public Map<String, PowerStateSubsystem> mSubsystemLowPowerStats = new ArrayMap<>();
+
+    /**
+     * Finds the PowerStatePlatformSleepState with the given name (creating it if it doesn't exist),
+     * updates its timeMs and count, and returns it.
+     */
+    @SuppressWarnings("unused")
+    public PowerStatePlatformSleepState getAndUpdatePlatformState(
+            String name, long timeMs, int count) {
+
+        PowerStatePlatformSleepState e = mPlatformLowPowerStats.get(name);
+        if (e == null) {
+            e = new PowerStatePlatformSleepState();
+            mPlatformLowPowerStats.put(name, e);
+        }
+        e.mTimeMs = timeMs;
+        e.mCount = count;
+        return e;
+    }
+
+    /**
+     * Returns the PowerStateSubsystem with the given name (creating it if it doesn't exist).
+     */
+    public PowerStateSubsystem getSubsystem(String name) {
+        PowerStateSubsystem e = mSubsystemLowPowerStats.get(name);
+        if (e == null) {
+            e = new PowerStateSubsystem();
+            mSubsystemLowPowerStats.put(name, e);
+        }
+        return e;
+    }
+
+    /** Represents a subsystem state or a platform voter. */
+    public static class PowerStateElement {
+        public long mTimeMs; // totalTimeInMsecVotedForSinceBoot
+        public int mCount; // totalNumberOfTimesVotedSinceBoot
+
+        private PowerStateElement(long timeMs, int count) {
+            this.mTimeMs = timeMs;
+            this.mCount = count;
+        }
+    }
+
+    /** Represents a PowerStatePlatformSleepState, per hardware/interfaces/power/1.0/types.hal */
+    public static class PowerStatePlatformSleepState {
+        public long mTimeMs; // residencyInMsecSinceBoot
+        public int mCount; // totalTransitions
+        public Map<String, PowerStateElement> mVoters = new ArrayMap<>(); // voters for this platform-level sleep state
+
+        /**
+         * Updates (creating if necessary) the voter with the given name, with the given timeMs and
+         * count.
+         */
+        @SuppressWarnings("unused")
+        public void putVoter(String name, long timeMs, int count) {
+            PowerStateElement e = mVoters.get(name);
+            if (e == null) {
+                mVoters.put(name, new PowerStateElement(timeMs, count));
+            } else {
+                e.mTimeMs = timeMs;
+                e.mCount = count;
+            }
+        }
+    }
+
+    /** Represents a PowerStateSubsystem, per hardware/interfaces/power/1.1/types.hal */
+    public static class PowerStateSubsystem {
+        public Map<String, PowerStateElement> mStates = new ArrayMap<>(); // sleep states supported by this susbsystem
+
+        /**
+         * Updates (creating if necessary) the subsystem state with the given name, with the given
+         * timeMs and count.
+         */
+        @SuppressWarnings("unused")
+        public void putState(String name, long timeMs, int count) {
+            PowerStateElement e = mStates.get(name);
+            if (e == null) {
+                mStates.put(name, new PowerStateElement(timeMs, count));
+            } else {
+                e.mTimeMs = timeMs;
+                e.mCount = count;
+            }
+        }
+    }
+}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index dafa68e..4e06577 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -1064,7 +1064,7 @@
         WindowManager.LayoutParams attrs = mWindow.getAttributes();
         int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility();
 
-        if (!mWindow.mIsFloating && ActivityManager.isHighEndGfx()) {
+        if (!mWindow.mIsFloating) {
             boolean disallowAnimate = !isLaidOut();
             disallowAnimate |= ((mLastWindowFlags ^ attrs.flags)
                     & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
@@ -1317,11 +1317,12 @@
                 v.setTag(new Pair<>(verticalBar, seascape));
             } else {
                 final LayerDrawable d = (LayerDrawable) v.getBackground();
-                final InsetDrawable inset = ((InsetDrawable) d.getDrawable(0));
-                ((ColorDrawable) inset.getDrawable()).setColor(dividerColor);
-                ((ColorDrawable) d.getDrawable(1)).setColor(color);
+                final InsetDrawable inset = ((InsetDrawable) d.getDrawable(1));
+                ((ColorDrawable) inset.getDrawable()).setColor(color);
+                ((ColorDrawable) d.getDrawable(0)).setColor(dividerColor);
             }
         } else {
+            v.setTag(null);
             v.setBackgroundColor(color);
         }
     }
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 2de9537..b13560c 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -2441,7 +2441,7 @@
 
         // Non-floating windows on high end devices must put up decor beneath the system bars and
         // therefore must know about visibility changes of those.
-        if (!mIsFloating && ActivityManager.isHighEndGfx()) {
+        if (!mIsFloating) {
             if (!targetPreL && a.getBoolean(
                     R.styleable.Window_windowDrawsSystemBarBackgrounds,
                     false)) {
diff --git a/core/java/com/android/internal/widget/NotificationExpandButton.java b/core/java/com/android/internal/widget/NotificationExpandButton.java
index b702898..39f82a5 100644
--- a/core/java/com/android/internal/widget/NotificationExpandButton.java
+++ b/core/java/com/android/internal/widget/NotificationExpandButton.java
@@ -31,7 +31,6 @@
  */
 @RemoteViews.RemoteView
 public class NotificationExpandButton extends ImageView {
-    private View mLabeledBy;
 
     public NotificationExpandButton(Context context) {
         super(context);
@@ -69,12 +68,5 @@
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
         info.setClassName(Button.class.getName());
-        if (mLabeledBy != null) {
-            info.setLabeledBy(mLabeledBy);
-        }
-    }
-
-    public void setLabeledBy(View labeledBy) {
-        mLabeledBy = labeledBy;
     }
 }
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index 592576b..e53162c 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -25,6 +25,7 @@
 import android.hardware.input.InputManager.InputDeviceListener;
 import android.os.SystemProperties;
 import android.util.Log;
+import android.util.Slog;
 import android.view.InputDevice;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -630,6 +631,12 @@
                     >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; // will be 0 for UP
 
             final int id = event.getPointerId(index);
+            if (id >= NP) {
+                Slog.wtf(TAG, "Got pointer ID out of bounds: id=" + id + " arraysize="
+                        + NP + " pointerindex=" + index
+                        + " action=0x" + Integer.toHexString(action));
+                return;
+            }
             final PointerState ps = mPointers.get(id);
             ps.mCurDown = false;
 
diff --git a/core/jni/android_os_HwBlob.cpp b/core/jni/android_os_HwBlob.cpp
index 0c23797..40d49b7 100644
--- a/core/jni/android_os_HwBlob.cpp
+++ b/core/jni/android_os_HwBlob.cpp
@@ -83,12 +83,6 @@
       mSize(size),
       mOwnsBuffer(true),
       mHandle(0) {
-    jclass clazz = env->GetObjectClass(thiz);
-    CHECK(clazz != NULL);
-
-    mClass = (jclass)env->NewGlobalRef(clazz);
-    mObject = env->NewWeakGlobalRef(thiz);
-
     if (size > 0) {
         mBuffer = malloc(size);
     }
@@ -99,14 +93,6 @@
         free(mBuffer);
         mBuffer = nullptr;
     }
-
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-
-    env->DeleteWeakGlobalRef(mObject);
-    mObject = NULL;
-
-    env->DeleteGlobalRef(mClass);
-    mClass = NULL;
 }
 
 void JHwBlob::setTo(const void *ptr, size_t handle) {
diff --git a/core/jni/android_os_HwBlob.h b/core/jni/android_os_HwBlob.h
index 0920488..39393cb 100644
--- a/core/jni/android_os_HwBlob.h
+++ b/core/jni/android_os_HwBlob.h
@@ -70,9 +70,6 @@
         sp<JHwBlob> mBlob;
     };
 
-    jclass mClass;
-    jobject mObject;
-
     void *mBuffer;
     size_t mSize;
     bool mOwnsBuffer;
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index b412b6a..9494fb8 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -166,10 +166,6 @@
       mOwnsParcel(false),
       mTransactCallback(nullptr),
       mWasSent(false) {
-    jclass clazz = env->GetObjectClass(thiz);
-    CHECK(clazz != NULL);
-
-    mObject = env->NewWeakGlobalRef(thiz);
 }
 
 JHwParcel::~JHwParcel() {
@@ -178,9 +174,6 @@
     mStorage.release(env);
 
     setParcel(NULL, false /* assumeOwnership */);
-
-    env->DeleteWeakGlobalRef(mObject);
-    mObject = NULL;
 }
 
 hardware::Parcel *JHwParcel::getParcel() {
diff --git a/core/jni/android_os_HwParcel.h b/core/jni/android_os_HwParcel.h
index f6e6100..2c26993 100644
--- a/core/jni/android_os_HwParcel.h
+++ b/core/jni/android_os_HwParcel.h
@@ -53,8 +53,6 @@
     virtual ~JHwParcel();
 
 private:
-    jobject mObject;
-
     hardware::Parcel *mParcel;
     bool mOwnsParcel;
 
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 5b0f776..883d4db 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -133,6 +133,14 @@
     jmethodID mCallback;
 } gStrictModeCallbackOffsets;
 
+static struct thread_dispatch_offsets_t
+{
+    // Class state.
+    jclass mClass;
+    jmethodID mDispatchUncaughtException;
+    jmethodID mCurrentThread;
+} gThreadDispatchOffsets;
+
 // ****************************************************************************
 // ****************************************************************************
 // ****************************************************************************
@@ -166,6 +174,23 @@
     return vm->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0 ? env : NULL;
 }
 
+// Report a java.lang.Error (or subclass). This may terminate the runtime.
+static void report_java_lang_error(JNIEnv* env, jthrowable error)
+{
+    // Try to run the uncaught exception machinery.
+    jobject thread = env->CallStaticObjectMethod(gThreadDispatchOffsets.mClass,
+            gThreadDispatchOffsets.mCurrentThread);
+    if (thread != nullptr) {
+        env->CallVoidMethod(thread, gThreadDispatchOffsets.mDispatchUncaughtException,
+                error);
+        // Should not return here, unless more errors occured.
+    }
+    // Some error occurred that meant that either dispatchUncaughtException could not be
+    // called or that it had an error itself (as this should be unreachable under normal
+    // conditions). Clear the exception.
+    env->ExceptionClear();
+}
+
 static void report_exception(JNIEnv* env, jthrowable excep, const char* msg)
 {
     env->ExceptionClear();
@@ -192,6 +217,10 @@
     }
 
     if (env->IsInstanceOf(excep, gErrorOffsets.mClass)) {
+        // Try to report the error. This should not return under normal circumstances.
+        report_java_lang_error(env, excep);
+        // The traditional handling: re-raise and abort.
+
         /*
          * It's an Error: Reraise the exception and ask the runtime to abort.
          */
@@ -1337,5 +1366,12 @@
     gStrictModeCallbackOffsets.mCallback = GetStaticMethodIDOrDie(env, clazz,
             "onBinderStrictModePolicyChange", "(I)V");
 
+    clazz = FindClassOrDie(env, "java/lang/Thread");
+    gThreadDispatchOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
+    gThreadDispatchOffsets.mDispatchUncaughtException = GetMethodIDOrDie(env, clazz,
+            "dispatchUncaughtException", "(Ljava/lang/Throwable;)V");
+    gThreadDispatchOffsets.mCurrentThread = GetStaticMethodIDOrDie(env, clazz, "currentThread",
+            "()Ljava/lang/Thread;");
+
     return 0;
 }
diff --git a/core/jni/com_android_internal_os_ClassLoaderFactory.cpp b/core/jni/com_android_internal_os_ClassLoaderFactory.cpp
index 7052e5f..9ce3289 100644
--- a/core/jni/com_android_internal_os_ClassLoaderFactory.cpp
+++ b/core/jni/com_android_internal_os_ClassLoaderFactory.cpp
@@ -27,15 +27,17 @@
                                               jint targetSdkVersion,
                                               jstring librarySearchPath,
                                               jstring libraryPermittedPath,
-                                              jboolean isShared) {
+                                              jboolean isShared,
+                                              jboolean isForVendor) {
     return android::CreateClassLoaderNamespace(env, targetSdkVersion,
                                                classLoader, isShared == JNI_TRUE,
+                                               isForVendor == JNI_TRUE,
                                                librarySearchPath, libraryPermittedPath);
 }
 
 static const JNINativeMethod g_methods[] = {
     { "createClassloaderNamespace",
-      "(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;",
+      "(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;ZZ)Ljava/lang/String;",
       reinterpret_cast<void*>(createClassloaderNamespace_native) },
 };
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 89bbec2..031c3f5 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -309,6 +309,10 @@
     <protected-broadcast android:name="com.android.server.usb.ACTION_OPEN_IN_APPS" />
     <protected-broadcast android:name="com.android.server.am.DELETE_DUMPHEAP" />
     <protected-broadcast android:name="com.android.server.net.action.SNOOZE_WARNING" />
+    <protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.USER_DISMISSED_NOTIFICATION" />
+    <protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.CONNECT_TO_NETWORK" />
+    <protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.PICK_WIFI_NETWORK" />
+    <protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.PICK_NETWORK_AFTER_FAILURE" />
     <protected-broadcast android:name="android.net.wifi.WIFI_STATE_CHANGED" />
     <protected-broadcast android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" />
     <protected-broadcast android:name="android.net.wifi.WIFI_CREDENTIAL_CHANGED" />
diff --git a/core/res/res/drawable-nodpi/platlogo.xml b/core/res/res/drawable-nodpi/platlogo.xml
index 182ba24..a6dee8a 100644
--- a/core/res/res/drawable-nodpi/platlogo.xml
+++ b/core/res/res/drawable-nodpi/platlogo.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
 <!--
 Copyright (C) 2017 The Android Open Source Project
 
@@ -14,27 +15,35 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="480dp"
-        android:height="480dp"
-        android:viewportWidth="48.0"
-        android:viewportHeight="48.0">
-    <path
-        android:pathData="M25.0,25.0m-20.5,0.0a20.5,20.5,0,1,1,41.0,0.0a20.5,20.5,0,1,1,-41.0,0.0"
-        android:fillAlpha="0.066"
-        android:fillColor="#000000"/>
-    <path
-        android:pathData="M24.0,24.0m-20.0,0.0a20.0,20.0,0,1,1,40.0,0.0a20.0,20.0,0,1,1,-40.0,0.0"
-        android:fillColor="#FFC107"/>
-    <path
-        android:pathData="M44,24.2010101 L33.9004889,14.101499 L14.101499,33.9004889 L24.2010101,44 C29.2525804,43.9497929 34.2887564,41.9975027 38.1431296,38.1431296 C41.9975027,34.2887564 43.9497929,29.2525804 44,24.2010101 Z"
-        android:fillColor="#FE9F00"/>
-    <path
-        android:pathData="M24.0,24.0m-14.0,0.0a14.0,14.0,0,1,1,28.0,0.0a14.0,14.0,0,1,1,-28.0,0.0"
-        android:fillColor="#FED44F"/>
-    <path
-        android:pathData="M37.7829445,26.469236 L29.6578482,18.3441397 L18.3441397,29.6578482 L26.469236,37.7829445 C29.1911841,37.2979273 31.7972024,36.0037754 33.9004889,33.9004889 C36.0037754,31.7972024 37.2979273,29.1911841 37.7829445,26.469236 Z"
-        android:fillColor="#FFC107"/>
-    <path
-        android:pathData="M24.0,24.0m-8.0,0.0a8.0,8.0,0,1,1,16.0,0.0a8.0,8.0,0,1,1,-16.0,0.0"
-        android:fillColor="#FFFFFF"/>
+    android:width="48dp"
+    android:height="48dp"
+    android:viewportWidth="48"
+    android:viewportHeight="48">
+    <group>
+        <path
+            android:fillColor="#2C292A"
+            android:fillType="evenOdd"
+            android:pathData="M6,26a20,20 0 0,1 40,0a20,20 0 0,1 -40,0z"/>
+        <path
+            android:fillColor="#FAFAFA"
+            android:fillType="evenOdd"
+            android:pathData="M4,24a20,20 0 0,1 40,0a20,20 0 0,1 -40,0z"/>
+        <path
+            android:fillColor="#2C292A"
+            android:fillType="evenOdd"
+            android:pathData="M2,22a20,20 0 0,1 40,0a20,20 0 0,1 -40,0z"/>
+        <path
+            android:fillColor="#00000000"
+            android:strokeColor="#453F41"
+            android:strokeWidth="1"
+            android:fillType="evenOdd"
+            android:pathData="M26.5 29.5v3c0 1.13-.87 2-2 2s-2-.87-2-2v-3h-1v3c0 1.13-.87 2-2 2s-2-.87-2-2v-3H17a1.5 1.5 0 0 1-1.5-1.5V17.5h13V28a1.5 1.5 0 0 1-1.5 1.5h-.5zM13.5 17.5c1.13 0 2 .87 2 2v7c0 1.13-.87 2-2 2s-2-.87-2-2v-7c0-1.13.87-2 2-2zM30.5 17.5c1.13 0 2 .87 2 2v7c0 1.13-.87 2-2 2s-2-.87-2-2v-7c0-1.13.87-2 2-2zM26.3 12.11A6.46 6.46 0 0 1 28.5 17v.5h-13V17a6.46 6.46 0 0 1 2.2-4.89l-.9-.9a.98.98 0 0 1 0-1.41.98.98 0 0 1 1.4 0l1.26 1.25A6.33 6.33 0 0 1 22 10.5c.87 0 1.73.2 2.54.55L25.8 9.8a.98.98 0 0 1 1.4 0 .98.98 0 0 1 0 1.4l-.9.91z"/>
+        <path
+            android:fillColor="#453F41"
+            android:fillType="evenOdd"
+            android:pathData="M20.16 14.5a.66.66 0 1 1-1.31 0c0-.36.29-.65.65-.65.36 0 .65.29.65.65zM25.16 14.5c0 .36-.3.66-.66.66a.65.65 0 1 1 .66-.66z"/>
+        <path
+            android:fillColor="#453F41"
+            android:pathData="M22 40.5c0.36 0 0.73-0.01 1.09-0.03l-0.18-3A15.77 15.77 0 0 1 22 37.5v3zm2.17-0.13a18.48 18.48 0 0 0 1.08-0.15l-0.53-2.96c-0.3 0.05-0.6 0.1-0.9 0.13l0.35 2.98zM26.32 40a18.37 18.37 0 0 0 1.05-0.28l-0.87-2.87a15.37 15.37 0 0 1-0.88 0.23l0.7 2.92zm2.1-0.64l-1.03-2.81a15.39 15.39 0 0 0 0.84-0.34l1.2 2.74a18.39 18.39 0 0 1-1 0.41zm1.99-0.87l-1.37-2.67a15.46 15.46 0 0 0 0.8-0.44l1.52 2.59a18.46 18.46 0 0 1-0.95 0.52zm1.89-1.11l-1.67-2.5a15.55 15.55 0 0 0 0.74-0.52l1.81 2.39a18.55 18.55 0 0 1-0.88 0.63zm1.75-1.33l-1.95-2.28a15.6 15.6 0 0 0 0.67-0.61l2.09 2.15a18.6 18.6 0 0 1-0.8 0.74zm1.6-1.55l-2.22-2.02a15.6 15.6 0 0 0 0.6-0.7l2.33 1.9a18.6 18.6 0 0 1-0.72 0.82zM37 32.82l-2.43-1.76a15.53 15.53 0 0 0 0.5-0.75l2.54 1.6c-0.2 0.31-0.4 0.61-0.61 0.9zm1.15-1.8l-2.62-1.47a15.45 15.45 0 0 0 0.42-0.8l2.7 1.3a18.45 18.45 0 0 1-0.5 0.97zm0.95-1.98l-2.77-1.14a15.38 15.38 0 0 0 0.32-0.86l2.84 0.98a18.38 18.38 0 0 1-0.39 1.02zm0.72-2.09c0.1-0.34 0.18-0.7 0.26-1.05l-2.93-0.63a15.38 15.38 0 0 1-0.22 0.88l2.89 0.8zm0.46-2.15a18.52 18.52 0 0 0 0.13-1.08l-2.99-0.28a15.52 15.52 0 0 1-0.1 0.9l2.96 0.46zm0.2-2.2a18.81 18.81 0 0 0 0-1.1l-3 0.08a16 16 0 0 1 0 0.92l3 0.1zm-0.06-2.2a18.54 18.54 0 0 0-0.12-1.07l-2.97 0.43c0.04 0.3 0.08 0.6 0.1 0.9l3-0.25zm-0.31-2.15a18.39 18.39 0 0 0-0.25-1.06l-2.9 0.78a15.39 15.39 0 0 1 0.21 0.89l2.94-0.6zm-0.57-2.12l-2.85 0.95a15.37 15.37 0 0 0-0.31-0.85l2.78-1.12a18.37 18.37 0 0 1 0.38 1.02zm-0.83-2.06l-2.71 1.29a15.44 15.44 0 0 0-0.42-0.81l2.63-1.45a18.44 18.44 0 0 1 0.5 0.97zm-1.03-1.88l-2.54 1.6a15.53 15.53 0 0 0-0.5-0.76l2.44-1.74 0.6 0.9zm-1.28-1.79l-2.33 1.88a15.6 15.6 0 0 0-0.6-0.69l2.23-2.02a18.6 18.6 0 0 1 0.7 0.83zm-1.48-1.63l-2.1 2.14a15.6 15.6 0 0 0-0.67-0.62l1.97-2.26a18.6 18.6 0 0 1 0.8 0.74zM33.24 7.3l-1.82 2.38a15.55 15.55 0 0 0-0.74-0.53l1.68-2.49c0.3 0.2 0.6 0.42 0.88 0.64zm-1.71-1.17L29.98 8.7a15.47 15.47 0 0 0-0.8-0.45l1.4-2.66a18.47 18.47 0 0 1 0.95 0.54zm-1.95-1.02l-1.23 2.74A15.4 15.4 0 0 0 27.5 7.5l1.06-2.8a18.4 18.4 0 0 1 1.01 0.4zm-2.06-0.78l-0.9 2.86a15.37 15.37 0 0 0-0.87-0.24l0.72-2.92a18.37 18.37 0 0 1 1.05 0.3zM25.38 3.8a18.47 18.47 0 0 0-1.08-0.17l-0.37 2.98c0.3 0.04 0.6 0.08 0.9 0.14l0.55-2.95zm-2.2-0.27A18.75 18.75 0 0 0 22.1 3.5l-0.02 3L23 6.53l0.19-3zM21 3.53a18.6 18.6 0 0 0-1.08 0.09l0.33 2.98a15.6 15.6 0 0 1 0.91-0.08l-0.16-3zm-2.16 0.24A18.4 18.4 0 0 0 17.76 4l0.68 2.92a15.4 15.4 0 0 1 0.9-0.18l-0.51-2.96zm-2.14 0.5l0.86 2.88a15.37 15.37 0 0 0-0.86 0.28l-1.03-2.81a18.37 18.37 0 0 1 1.03-0.35zm-2.07 0.76l1.2 2.75a15.42 15.42 0 0 0-0.83 0.4L13.63 5.5a18.42 18.42 0 0 1 0.99-0.47zM12.7 6l1.5 2.6a15.5 15.5 0 0 0-0.76 0.48l-1.66-2.5A18.5 18.5 0 0 1 12.7 6zm-1.83 1.22l1.8 2.4a15.58 15.58 0 0 0-0.7 0.57L10.01 7.9a18.58 18.58 0 0 1 0.85-0.68zM9.19 8.66l2.07 2.16a15.6 15.6 0 0 0-0.63 0.65l-2.2-2.04a18.6 18.6 0 0 1 0.76-0.77zm-1.51 1.63l2.32 1.9a15.57 15.57 0 0 0-0.56 0.72l-2.42-1.76a18.57 18.57 0 0 1 0.66-0.86zm-1.23 1.69l2.52 1.62a15.5 15.5 0 0 0-0.47 0.78l-2.61-1.47a18.5 18.5 0 0 1 0.56-0.93zm-1.08 1.9l2.7 1.32a15.41 15.41 0 0 0-0.38 0.83l-2.77-1.15a18.41 18.41 0 0 1 0.45-1zm-0.85 2.04l2.84 0.98a15.37 15.37 0 0 0-0.28 0.87L4.2 16.96c0.1-0.35 0.2-0.7 0.32-1.04zm-0.6 2.12a18.43 18.43 0 0 0-0.2 1.07l2.97 0.47c0.05-0.3 0.1-0.6 0.17-0.9l-2.93-0.64zm-0.34 2.18a18.65 18.65 0 0 0-0.07 1.09l3 0.11 0.06-0.91-2.99-0.29zm-0.08 2.2a18.7 18.7 0 0 0 0.06 1.1l3-0.25a15.7 15.7 0 0 1-0.06-0.91l-3 0.07zm0.18 2.18a18.44 18.44 0 0 0 0.18 1.07l2.95-0.6a15.44 15.44 0 0 1-0.16-0.9L3.68 24.6zm0.43 2.14l2.9-0.77a15.37 15.37 0 0 0 0.26 0.88l-2.85 0.94a18.37 18.37 0 0 1-0.3-1.05zm0.7 2.1l2.78-1.11a15.4 15.4 0 0 0 0.36 0.83l-2.71 1.27a18.4 18.4 0 0 1-0.44-1zm0.9 1.95l2.65-1.43a15.48 15.48 0 0 0 0.45 0.8l-2.55 1.57a18.48 18.48 0 0 1-0.54-0.94zm1.17 1.87l2.45-1.73a15.56 15.56 0 0 0 0.54 0.73l-2.34 1.87a18.56 18.56 0 0 1-0.65-0.87zm1.37 1.72l2.23-2a15.6 15.6 0 0 0 0.63 0.65l-2.1 2.14a18.6 18.6 0 0 1-0.76-0.79zm1.58 1.56l1.98-2.26c0.22 0.2 0.46 0.39 0.7 0.58l-1.84 2.37a18.59 18.59 0 0 1-0.84-0.7zm1.66 1.28l1.7-2.46a15.52 15.52 0 0 0 0.77 0.5l-1.56 2.56a18.52 18.52 0 0 1-0.91-0.6zm1.87 1.14l1.4-2.65a15.43 15.43 0 0 0 0.82 0.4l-1.24 2.73a18.43 18.43 0 0 1-0.98-0.48zm2 0.91l1.08-2.8a15.37 15.37 0 0 0 0.86 0.3l-0.9 2.86a18.37 18.37 0 0 1-1.04-0.36zm2.1 0.67a18.4 18.4 0 0 0 1.07 0.23l0.56-2.94a15.4 15.4 0 0 1-0.9-0.2l-0.72 2.91zm2.18 0.41a18.57 18.57 0 0 0 1.08 0.1l0.2-2.99a15.57 15.57 0 0 1-0.9-0.09l-0.38 2.98zm2.2 0.15H22v-3h-0.13l-0.03 3z"/>
+    </group>
 </vector>
diff --git a/core/res/res/drawable-nodpi/platlogo_m.xml b/core/res/res/drawable-nodpi/platlogo_m.xml
index d9a558d..aacf674 100644
--- a/core/res/res/drawable-nodpi/platlogo_m.xml
+++ b/core/res/res/drawable-nodpi/platlogo_m.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2016 The Android Open Source Project
+Copyright (C) 2017 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.
@@ -14,59 +14,27 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="48dp"
-        android:height="48dp"
+        android:width="480dp"
+        android:height="480dp"
         android:viewportWidth="48.0"
         android:viewportHeight="48.0">
+    <!--<path
+        android:pathData="M25.0,25.0m-20.5,0.0a20.5,20.5,0,1,1,41.0,0.0a20.5,20.5,0,1,1,-41.0,0.0"
+        android:fillAlpha="0.066"
+        android:fillColor="#000000"/>-->
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M33.8,38l-25.5,-25.5l-1.7000003,0.6999998l25.499998,25.5z"/>
+        android:pathData="M24.0,24.0m-20.0,0.0a20.0,20.0,0,1,1,40.0,0.0a20.0,20.0,0,1,1,-40.0,0.0"
+        android:fillColor="#FFC107"/>
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M40.8,34.8l-25.4,-25.5l-1.6999998,0.6999998l25.5,25.5z"/>
+        android:pathData="M44,24.2010101 L33.9004889,14.101499 L14.101499,33.9004889 L24.2010101,44 C29.2525804,43.9497929 34.2887564,41.9975027 38.1431296,38.1431296 C41.9975027,34.2887564 43.9497929,29.2525804 44,24.2010101 Z"
+        android:fillColor="#FE9F00"/>
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M11.1,13.1l-0.3,-0.4l1.1,-1.3l0,0l-1.6,0.8l-0.4,-0.4l2.6,-1.2l0.4,0.4l-1.1,1.3l0,0l1.6,-0.8l0.3,0.4L11.1,13.1z"/>
+        android:pathData="M24.0,24.0m-14.0,0.0a14.0,14.0,0,1,1,28.0,0.0a14.0,14.0,0,1,1,-28.0,0.0"
+        android:fillColor="#FED44F"/>
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M13,14.2l-0.5,-0.5l-0.6,0.2l-0.4,-0.4l3.1,-0.7l0.4,0.4l-2.1,1.7l-0.4,-0.4L13,14.2z M13,13.6l0.3,0.3l0.8,-0.6   l0,0L13,13.6z"/>
+        android:pathData="M37.7829445,26.469236 L29.6578482,18.3441397 L18.3441397,29.6578482 L26.469236,37.7829445 C29.1911841,37.2979273 31.7972024,36.0037754 33.9004889,33.9004889 C36.0037754,31.7972024 37.2979273,29.1911841 37.7829445,26.469236 Z"
+        android:fillColor="#FFC107"/>
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M16.3,14.6l-1.6,1.2l0,0l2.2,-0.6l0.5,0.5l-2.6,1.2l-0.3,-0.4l0.7,-0.3l1,-0.4l0,0l-2.1,0.5L13.9,16l1.4,-1.1l0,0   l-0.9,0.5l-0.7,0.3l-0.3,-0.4l2.6,-1.2L16.3,14.6z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M17.4,17.8l-0.6,-0.6l-0.7,0.3l0.7,0.7l-0.4,0.2l-1,-1l2.6,-1.2l1,1l-0.4,0.2l-0.7,-0.7L17.2,17l0.6,0.6L17.4,17.8   z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M18.8,18.7L18.8,18.7l1.3,-0.2l0.4,0.4l-2.1,0.3l-0.9,0.4l-0.3,-0.4l1,-0.4l1.2,-1.2l0.4,0.4L18.8,18.7z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M22.2,20.5l-1.6,1.2l0,0l2.2,-0.6l0.5,0.5l-2.6,1.2l-0.3,-0.4l0.7,-0.3l1,-0.4l0,0L20,22.1l-0.2,-0.2l1.4,-1.1l0,0   l-0.9,0.5l-0.7,0.3l-0.3,-0.4l2.6,-1.2L22.2,20.5z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M22,23.6c0,0,0.1,0.1,0.2,0.1c0.1,0,0.2,0,0.3,-0.1l0.3,0.3c-0.2,0.1,-0.4,0.1,-0.6,0.1c-0.2,0,-0.4,-0.1,-0.5,-0.2   c-0.2,-0.2,-0.2,-0.3,-0.1,-0.5c0.1,-0.2,0.2,-0.3,0.5,-0.4l0.2,-0.1c0.3,-0.1,0.5,-0.2,0.8,-0.2c0.2,0,0.5,0.1,0.6,0.3   c0.1,0.1,0.2,0.3,0.1,0.4c0,0.1,-0.2,0.3,-0.4,0.4L23,23.4c0.1,0,0.2,-0.1,0.2,-0.2c0,-0.1,0,-0.1,0,-0.2C23.1,23,23,22.9,22.9,23   c-0.1,0,-0.2,0.1,-0.4,0.1l-0.2,0.1c-0.2,0.1,-0.3,0.1,-0.3,0.2C21.9,23.5,21.9,23.5,22,23.6z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M23.8,25.9l-0.3,-0.4l1.1,-1.3l0,0L22.9,25l-0.4,-0.4l2.6,-1.2l0.4,0.4l-1.1,1.3l0,0l1.6,-0.8l0.3,0.4L23.8,25.9z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M25.7,27l-0.5,-0.5l-0.6,0.2l-0.4,-0.4l3.1,-0.7l0.4,0.4l-2.1,1.7l-0.4,-0.4L25.7,27z M25.7,26.4l0.3,0.3l0.8,-0.6   l0,0L25.7,26.4z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M29,27.4l-1.6,1.2l0,0l2.2,-0.6l0.5,0.5l-2.6,1.2l-0.3,-0.4l0.8,-0.3l1,-0.4l0,0L26.8,29l-0.2,-0.2l1.4,-1.1l0,0   L27,28.1l-0.8,0.3l-0.3,-0.4l2.6,-1.2L29,27.4z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M30,30.6L29.5,30l-0.7,0.3l0.7,0.7L29,31.2l-1,-1l2.6,-1.2l1,1l-0.4,0.2l-0.7,-0.7l-0.6,0.3l0.6,0.6L30,30.6z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M31.5,32.1l-0.6,-0.6L29.8,32l-0.4,-0.4l2.6,-1.2l1,1l-0.4,0.2L32,31l-0.7,0.3l0.6,0.6L31.5,32.1z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M32,33.5L31.6,33L31,33.2l-0.4,-0.4l3.1,-0.7l0.4,0.4l-2.1,1.7l-0.4,-0.4L32,33.5z M32.1,32.9l0.3,0.3l0.8,-0.6   l0,0L32.1,32.9z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M34.3,35.3c-0.3,0.1,-0.5,0.2,-0.8,0.1c-0.2,0,-0.5,-0.1,-0.6,-0.3c-0.2,-0.2,-0.2,-0.4,-0.2,-0.5   c0.1,-0.2,0.2,-0.3,0.6,-0.5l0.8,-0.4c0.3,-0.1,0.6,-0.2,0.9,-0.2c0.3,0,0.5,0.1,0.7,0.3c0.2,0.2,0.3,0.4,0.2,0.5c0,0.2,-0.2,0.3,-0.5,0.5   l-0.3,-0.4c0.2,-0.1,0.3,-0.1,0.3,-0.2c0,-0.1,0,-0.1,-0.1,-0.2C35,34,34.9,34,34.8,34c-0.1,0,-0.3,0,-0.5,0.1l-0.8,0.4   c-0.2,0.1,-0.3,0.2,-0.4,0.2c0,0.1,0,0.1,0,0.2c0.1,0.1,0.2,0.1,0.3,0.1c0.1,0,0.2,0,0.4,-0.1L34.3,35.3z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M36,36.6L35.4,36l-0.7,0.3l0.7,0.7l-0.4,0.2l-1,-1l2.6,-1.2l1,1l-0.4,0.2l-0.7,-0.7l-0.6,0.3l0.6,0.6L36,36.6z"/>
+        android:pathData="M24.0,24.0m-8.0,0.0a8.0,8.0,0,1,1,16.0,0.0a8.0,8.0,0,1,1,-16.0,0.0"
+        android:fillColor="#FFFFFF"/>
 </vector>
diff --git a/core/res/res/drawable-nodpi/stat_sys_adb.xml b/core/res/res/drawable-nodpi/stat_sys_adb.xml
index 89e42e6..2e2b395 100644
--- a/core/res/res/drawable-nodpi/stat_sys_adb.xml
+++ b/core/res/res/drawable-nodpi/stat_sys_adb.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
 <!--
 Copyright (C) 2017 The Android Open Source Project
 
@@ -14,19 +15,23 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M12.0,12.0m-10.0,0.0a10.0,10.0,0,1,1,20.0,0.0a10.0,10.0,0,1,1,-20.0,0.0"
-        android:fillAlpha="0.25"/>
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M12,22 C6.4771525,22 2,17.5228475 2,12 C2,6.4771525 6.4771525,2 12,2 C17.5228475,2 22,6.4771525 22,12 C22,17.5228475 17.5228475,22 12,22 Z M12,18.5 C15.5898509,18.5 18.5,15.5898509 18.5,12 C18.5,8.41014913 15.5898509,5.5 12,5.5 C8.41014913,5.5 5.5,8.41014913 5.5,12 C5.5,15.5898509 8.41014913,18.5 12,18.5 Z"/>
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M12,18.5 C8.41014913,18.5 5.5,15.5898509 5.5,12 C5.5,8.41014913 8.41014913,5.5 12,5.5 C15.5898509,5.5 18.5,8.41014913 18.5,12 C18.5,15.5898509 15.5898509,18.5 12,18.5 Z M12,15 C13.6568542,15 15,13.6568542 15,12 C15,10.3431458 13.6568542,9 12,9 C10.3431458,9 9,10.3431458 9,12 C9,13.6568542 10.3431458,15 12,15 Z"
-        android:fillAlpha="0.25"/>
-</vector>
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <group>
+        <path
+            android:fillColor="#FFFFFF"
+            android:fillAlpha=".33"
+            android:fillType="evenOdd"
+            android:pathData="M5.71 18.29A8.99 8.99 0 0 0 22 13c0-3-1.46-5.65-3.71-7.29A8.99 8.99 0 0 0 2 11c0 3 1.46 5.65 3.71 7.29z"/>
+        <path
+            android:fillColor="#FFFFFF"
+            android:fillType="evenOdd"
+            android:pathData="M7.25 19.18A8.5 8.5 0 0 0 19.19 7.24 9 9 0 0 1 7.24 19.19z"/>
+        <path
+            android:fillColor="#FFFFFF"
+            android:fillAlpha=".33"
+            android:pathData="M10.5 3a0.5 0.5 0 1 1 1 0v2.05a0.5 0.5 0 1 1-1 0V3zm3.1 0.42a0.5 0.5 0 0 1 0.93 0.39l-0.8 1.88A0.5 0.5 0 1 1 12.8 5.3l0.8-1.88zm2.7 1.57a0.5 0.5 0 1 1 0.71 0.7l-1.45 1.46a0.5 0.5 0 0 1-0.7-0.71l1.44-1.45zm1.9 2.5a0.5 0.5 0 0 1 0.38 0.92l-1.9 0.77a0.5 0.5 0 0 1-0.37-0.93l1.9-0.77zM19 10.5a0.5 0.5 0 1 1 0 1h-2.05a0.5 0.5 0 0 1 0-1H19zm-0.42 3.1a0.5 0.5 0 0 1-0.39 0.93l-1.88-0.8a0.5 0.5 0 1 1 0.39-0.92l1.88 0.8zm-1.57 2.7a0.5 0.5 0 1 1-0.7 0.71l-1.46-1.45a0.5 0.5 0 0 1 0.71-0.7l1.45 1.44zm-2.5 1.9a0.5 0.5 0 1 1-0.92 0.38l-0.77-1.9a0.5 0.5 0 0 1 0.93-0.37l0.77 1.9zM11.5 19a0.5 0.5 0 1 1-1 0v-2.05a0.5 0.5 0 0 1 1 0V19zm-3.1-0.42a0.5 0.5 0 0 1-0.93-0.39l0.8-1.88A0.5 0.5 0 0 1 9.2 16.7l-0.8 1.88zm-2.7-1.57a0.5 0.5 0 1 1-0.71-0.7l1.45-1.46a0.5 0.5 0 0 1 0.7 0.71L5.7 17.01zm-1.9-2.48a0.5 0.5 0 0 1-0.38-0.92l1.88-0.8a0.5 0.5 0 0 1 0.4 0.92l-1.9 0.8zM3 11.5a0.5 0.5 0 1 1 0-1h2.05a0.5 0.5 0 1 1 0 1H3zm0.42-3.1A0.5 0.5 0 0 1 3.8 7.46l1.88 0.8A0.5 0.5 0 1 1 5.3 9.2L3.42 8.4zm1.57-2.7a0.5 0.5 0 1 1 0.7-0.71l1.46 1.45a0.5 0.5 0 0 1-0.71 0.7L4.99 5.7zm2.5-1.9A0.5 0.5 0 0 1 8.4 3.41l0.77 1.9a0.5 0.5 0 0 1-0.93 0.37L7.48 3.8z"/>
+    </group>
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_close.xml b/core/res/res/drawable/ic_close.xml
index 7086959..70565f2 100644
--- a/core/res/res/drawable/ic_close.xml
+++ b/core/res/res/drawable/ic_close.xml
@@ -19,6 +19,6 @@
         android:viewportWidth="24.0"
         android:viewportHeight="24.0">
     <path
-        android:pathData="M19.000000,6.400000l-1.400000,-1.400000 -5.600000,5.600000 -5.600000,-5.600000 -1.400000,1.400000 5.600000,5.600000 -5.600000,5.600000 1.400000,1.400000 5.600000,-5.600000 5.600000,5.600000 1.400000,-1.400000 -5.600000,-5.600000z"
+        android:pathData="M18.3,5.71a0.996,0.996 0,0 0,-1.41 0L12,10.59 7.11,5.7A0.996,0.996 0,1 0,5.7 7.11L10.59,12 5.7,16.89a0.996,0.996 0,1 0,1.41 1.41L12,13.41l4.89,4.89a0.996,0.996 0,1 0,1.41 -1.41L13.41,12l4.89,-4.89c0.38,-0.38 0.38,-1.02 0,-1.4z"
         android:fillColor="#FF000000"/>
 </vector>
diff --git a/core/res/res/drawable/ic_eject_24dp.xml b/core/res/res/drawable/ic_eject_24dp.xml
index 1bb351a..321ee3b 100644
--- a/core/res/res/drawable/ic_eject_24dp.xml
+++ b/core/res/res/drawable/ic_eject_24dp.xml
@@ -20,5 +20,8 @@
         android:viewportHeight="24.0">
     <path
         android:fillColor="#FF000000"
-        android:pathData="M5 17h14v2H5zm7,-12L5.33 15h13.34z"/>
+        android:pathData="M6,17h12c0.55,0 1,0.45 1,1v0c0,0.55 -0.45,1 -1,1H6c-0.55,0 -1,-0.45 -1,-1v0C5,17.45 5.45,17 6,17z"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M11.1,5.48l-5.22,7.83C5.39,14.03 5.91,15 6.78,15h10.44c0.87,0 1.39,-0.97 0.9,-1.69L12.9,5.48C12.47,4.84 11.53,4.84 11.1,5.48z"/>
 </vector>
diff --git a/core/res/res/drawable/ic_feedback.xml b/core/res/res/drawable/ic_feedback.xml
index 365863d..c316e7d 100644
--- a/core/res/res/drawable/ic_feedback.xml
+++ b/core/res/res/drawable/ic_feedback.xml
@@ -20,5 +20,5 @@
         android:viewportHeight="24.0">
     <path
         android:fillColor="#FF000000"
-        android:pathData="M20.0,2.0L4.0,2.0c-1.1,0.0 -1.9,0.9 -1.99,2.0L2.0,22.0l4.0,-4.0l14.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L22.0,4.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0zm-7.0,12.0l-2.0,0.0l0.0,-2.0l2.0,0.0l0.0,2.0zm0.0,-4.0l-2.0,0.0L11.0,6.0l2.0,0.0l0.0,4.0z"/>
+        android:pathData="M20,2H4C2.9,2 2,2.9 2,4v17.39c0,0.54 0.65,0.81 1.04,0.43L6.86,18H20c1.1,0 2,-0.9 2,-2V4C22,2.9 21.1,2 20,2zM11,7c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v3c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1V7zM12,15.2c-0.61,0 -1.1,-0.49 -1.1,-1.1c0,-0.61 0.49,-1.1 1.1,-1.1c0.61,0 1.1,0.49 1.1,1.1C13.1,14.71 12.61,15.2 12,15.2z"/>
 </vector>
diff --git a/core/res/res/drawable/ic_refresh.xml b/core/res/res/drawable/ic_refresh.xml
index 1297407..5894f95 100644
--- a/core/res/res/drawable/ic_refresh.xml
+++ b/core/res/res/drawable/ic_refresh.xml
@@ -20,5 +20,5 @@
         android:viewportHeight="24.0">
     <path
         android:fillColor="#FF000000"
-        android:pathData="M17.65,6.35C16.2,4.9 14.21,4.0 12.0,4.0c-4.42,0.0 -7.99,3.58 -7.99,8.0s3.57,8.0 7.99,8.0c3.73,0.0 6.84,-2.55 7.73,-6.0l-2.08,0.0c-0.82,2.33 -3.04,4.0 -5.65,4.0 -3.31,0.0 -6.0,-2.69 -6.0,-6.0s2.69,-6.0 6.0,-6.0c1.66,0.0 3.1,0.69 4.22,1.78L13.0,11.0l7.0,0.0L20.0,4.0l-2.35,2.35z"/>
+        android:pathData="M17.65,6.35c-1.63,-1.63 -3.94,-2.57 -6.48,-2.31c-3.67,0.37 -6.69,3.35 -7.1,7.02C3.52,15.91 7.27,20 12,20c3.19,0 5.93,-1.87 7.21,-4.57c0.31,-0.66 -0.16,-1.43 -0.89,-1.43h-0.01c-0.37,0 -0.72,0.2 -0.88,0.53c-1.13,2.43 -3.84,3.97 -6.81,3.32c-2.22,-0.49 -4.01,-2.3 -4.49,-4.52C5.31,9.44 8.26,6 12,6c1.66,0 3.14,0.69 4.22,1.78l-2.37,2.37C13.54,10.46 13.76,11 14.21,11H19c0.55,0 1,-0.45 1,-1V5.21c0,-0.45 -0.54,-0.67 -0.85,-0.35L17.65,6.35z"/>
 </vector>
diff --git a/core/res/res/layout/autofill_save.xml b/core/res/res/layout/autofill_save.xml
index 50ff50f..5c5b985 100644
--- a/core/res/res/layout/autofill_save.xml
+++ b/core/res/res/layout/autofill_save.xml
@@ -44,9 +44,16 @@
                 android:layout_height="wrap_content"
                 android:orientation="horizontal">
 
+                <ImageView
+                    android:id="@+id/autofill_save_icon"
+                    android:scaleType="fitStart"
+                    android:layout_width="24dp"
+                    android:layout_height="24dp"/>
+
                 <TextView
                     android:id="@+id/autofill_save_title"
-                    android:layout_width="0dp"
+                    android:paddingLeft="8dp"
+                    android:layout_width="fill_parent"
                     android:layout_height="wrap_content"
                     android:text="@string/autofill_save_title"
                     android:textSize="16sp"
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index df1d4cb..737bc09 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -133,7 +133,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Samo Wi-Fi"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nije prosleđeno"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
-    <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> nakon <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunde(i)"</string>
+    <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> nakon <xliff:g id="TIME_DELAY">{2}</xliff:g> sekunde/i"</string>
     <string name="cfTemplateRegistered" msgid="5073237827620166285">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nije prosleđeno"</string>
     <string name="cfTemplateRegisteredTime" msgid="6781621964320635172">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Nije prosleđeno"</string>
     <string name="fcComplete" msgid="3118848230966886575">"Kôd funkcije je izvršen."</string>
@@ -730,19 +730,19 @@
     <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"Pogledajte Korisnički vodič ili kontaktirajte Korisničku podršku."</string>
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM kartica je zaključana."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Otključavanje SIM kartice…"</string>
-    <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"<xliff:g id="NUMBER_0">%1$d</xliff:g> puta ste nepravilno nacrtali šablon za otključavanje. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
-    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"<xliff:g id="NUMBER_0">%1$d</xliff:g> puta ste pogrešno uneli lozinku. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
-    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"<xliff:g id="NUMBER_0">%1$d</xliff:g> puta ste pogrešno uneli PIN. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"<xliff:g id="NUMBER_0">%1$d</xliff:g> puta ste netačno uneli šablon za otključavanje. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> nesupešna(ih) pokušaja, od vas će biti zatraženo da otključate tablet pomoću podataka za prijavljivanje na Google.\n\n Probajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde(i)."</string>
+    <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"<xliff:g id="NUMBER_0">%1$d</xliff:g> puta ste nepravilno nacrtali šablon za otključavanje. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde/i."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"<xliff:g id="NUMBER_0">%1$d</xliff:g> puta ste pogrešno uneli lozinku. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde/i."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"<xliff:g id="NUMBER_0">%1$d</xliff:g> puta ste pogrešno uneli PIN. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde/i."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"<xliff:g id="NUMBER_0">%1$d</xliff:g> puta ste netačno uneli šablon za otključavanje. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> nesupešna(ih) pokušaja, od vas će biti zatraženo da otključate tablet pomoću podataka za prijavljivanje na Google.\n\n Probajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde/i."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"Neispravno ste nacrtali šablon za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja od vas će biti zatraženo da otključate TV pomoću podataka za prijavljivanje na Google.\n\n Probajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"<xliff:g id="NUMBER_0">%1$d</xliff:g> puta ste netačno uneli šablon za otključavanje. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> nesupešna(ih) pokušaja, od vas će biti zatraženo da otključate telefon pomoću podataka za prijavljivanje na Google.\n\n Probajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde(i)."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"<xliff:g id="NUMBER_0">%1$d</xliff:g> puta ste netačno uneli šablon za otključavanje. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> nesupešna(ih) pokušaja, od vas će biti zatraženo da otključate telefon pomoću podataka za prijavljivanje na Google.\n\n Probajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde/i."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Nepravilno ste pokušali da otključate tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Nakon još neuspešnih pokušaja (<xliff:g id="NUMBER_1">%2$d</xliff:g>) tablet će biti resetovan na fabrička podešavanja i svi korisnički podaci će biti izgubljeni."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="950408382418270260">"Pokušali ste da otključate TV netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja TV će biti resetovan na podrazumevana fabrička podešavanja i svi korisnički podaci će biti izgubljeni."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Neispravno ste pokušali da otključate telefon <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Nakon još neuspešnih pokušaja (<xliff:g id="NUMBER_1">%2$d</xliff:g>) telefon će biti resetovan na fabrička podešavanja i svi korisnički podaci će biti izgubljeni."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"Neispravno ste pokušali da otključate tablet <xliff:g id="NUMBER">%d</xliff:g> puta. Tablet će sada biti vraćen na podrazumevana fabrička podešavanja."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="3195755534096192191">"Pokušali ste da otključate TV netačno <xliff:g id="NUMBER">%d</xliff:g> puta. TV će sada biti resetovan na podrazumevana fabrička podešavanja."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Neispravno ste pokušali da otključate telefon <xliff:g id="NUMBER">%d</xliff:g> puta. Telefon će sada biti vraćen na podrazumevana fabrička podešavanja."</string>
-    <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Probajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> sekunde(i)."</string>
+    <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Probajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> sekunde/i."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Zaboravili ste šablon?"</string>
     <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Otključavanje naloga"</string>
     <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"Previše pokušaja unosa šablona"</string>
@@ -874,7 +874,7 @@
     <string name="second" msgid="3184235808021478">"sek"</string>
     <string name="seconds" msgid="3161515347216589235">"sek"</string>
     <string name="week" msgid="5617961537173061583">"nedelja"</string>
-    <string name="weeks" msgid="6509623834583944518">"nedelje(a)"</string>
+    <string name="weeks" msgid="6509623834583944518">"nedelje/a"</string>
     <string name="year" msgid="4001118221013892076">"godina"</string>
     <string name="years" msgid="6881577717993213522">"godine(a)"</string>
     <string name="now_string_shortest" msgid="8912796667087856402">"sada"</string>
@@ -1457,7 +1457,7 @@
     <string name="kg_wrong_pattern" msgid="1850806070801358830">"Pogrešan šablon"</string>
     <string name="kg_wrong_password" msgid="2333281762128113157">"Pogrešna lozinka"</string>
     <string name="kg_wrong_pin" msgid="1131306510833563801">"Pogrešan PIN"</string>
-    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Probajte ponovo za <xliff:g id="NUMBER">%1$d</xliff:g> sekunde(i)."</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Probajte ponovo za <xliff:g id="NUMBER">%1$d</xliff:g> sekunde/i."</string>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"Nacrtajte šablon"</string>
     <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Unesite PIN SIM kartice"</string>
     <string name="kg_pin_instructions" msgid="2377242233495111557">"Unesite PIN"</string>
@@ -1479,18 +1479,18 @@
     <string name="kg_login_invalid_input" msgid="5754664119319872197">"Nevažeće korisničko ime ili lozinka."</string>
     <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Zaboravili ste korisničko ime ili lozinku?\nPosetite adresu "<b>"google.com/accounts/recovery"</b>"."</string>
     <string name="kg_login_checking_password" msgid="1052685197710252395">"Provera naloga…"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Uneli ste netačni PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Uneli ste netačnu lozinku <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
-    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde(i)."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Uneli ste netačni PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde/i."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Uneli ste netačnu lozinku <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde/i."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunde/i."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Pokušali ste da otključate tablet netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Nakon još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja tablet će biti resetovan na fabrička podešavanja i svi korisnički podaci će biti izgubljeni."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="5621231220154419413">"Pokušali ste da otključate TV netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja TV će biti resetovan na podrazumevana fabrička podešavanja i svi korisnički podaci će biti izgubljeni."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Pokušali ste da otključate telefon netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja telefon će biti resetovan na fabrička podešavanja i svi korisnički podaci će biti izgubljeni."</string>
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Pokušali ste da otključate tablet netačno <xliff:g id="NUMBER">%d</xliff:g> puta. Tablet će sada biti vraćen na podrazumevana fabrička podešavanja."</string>
     <string name="kg_failed_attempts_now_wiping" product="tv" msgid="4987878286750741463">"Pokušali ste da otključate TV netačno <xliff:g id="NUMBER">%d</xliff:g> puta. TV će sada biti resetovan na podrazumevana fabrička podešavanja."</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Pokušali ste da otključate telefon netačno <xliff:g id="NUMBER">%d</xliff:g> puta. Telefon će sada biti vraćen na podrazumevana fabrička podešavanja."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja, od vas će biti zatraženo da otključate tablet pomoću naloga e-pošte.\n\nProbajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde(i)."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja, od vas će biti zatraženo da otključate tablet pomoću naloga e-pošte.\n\nProbajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde/i."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"Neispravno ste nacrtali šablon za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja, od vas će biti zatraženo da otključate TV pomoću naloga e-pošte.\n\n Probajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja, od vas će biti zatraženo da otključate telefon pomoću naloga e-pošte.\n\nProbajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde(i)."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja, od vas će biti zatraženo da otključate telefon pomoću naloga e-pošte.\n\nProbajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde/i."</string>
     <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Ukloni"</string>
     <string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"Želite da pojačate zvuk iznad preporučenog nivoa?\n\nSlušanje glasne muzike duže vreme može da vam ošteti sluh."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 611191a..4fba55a 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1084,7 +1084,7 @@
     <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Benachrichtigungstöne"</string>
     <string name="ringtone_unknown" msgid="3914515995813061520">"Unbekannt"</string>
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
-      <item quantity="other">WLANe verfügbar</item>
+      <item quantity="other">WLANs verfügbar</item>
       <item quantity="one">WLAN verfügbar</item>
     </plurals>
     <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 8069810..2dab4c2 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -38,7 +38,7 @@
     <string name="serviceErased" msgid="1288584695297200972">"Η διαγραφή ήταν επιτυχής."</string>
     <string name="passwordIncorrect" msgid="7612208839450128715">"Λανθασμένος κωδικός πρόσβασης."</string>
     <string name="mmiComplete" msgid="8232527495411698359">"Το MMI ολοκληρώθηκε."</string>
-    <string name="badPin" msgid="9015277645546710014">"Ο παλιός αριθμός PIN που πληκτρολογήσατε είναι λάθος."</string>
+    <string name="badPin" msgid="9015277645546710014">"Το παλιό PIN που πληκτρολογήσατε είναι λάθος."</string>
     <string name="badPuk" msgid="5487257647081132201">"Ο κωδικός PUK που πληκτρολογήσατε είναι λάθος."</string>
     <string name="mismatchPin" msgid="609379054496863419">"Οι αριθμοί PIN που πληκτρολογήσατε δεν ταιριάζουν."</string>
     <string name="invalidPin" msgid="3850018445187475377">"Πληκτρολογήστε έναν αριθμό PIN μεγέθους 4 έως 8 αριθμών."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 81c02b1..8048014 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1414,7 +1414,7 @@
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"Järjestelmä"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-ääni"</string>
     <string name="wireless_display_route_description" msgid="9070346425023979651">"Langaton näyttö"</string>
-    <string name="media_route_button_content_description" msgid="591703006349356016">"Lähetä"</string>
+    <string name="media_route_button_content_description" msgid="591703006349356016">"Suoratoisto"</string>
     <string name="media_route_chooser_title" msgid="1751618554539087622">"Yhdistä laitteeseen"</string>
     <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"Lähetä näyttö laitteeseen"</string>
     <string name="media_route_chooser_searching" msgid="4776236202610828706">"Etsitään laitteita…"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 843f5b9..ee7a0b2 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -840,9 +840,9 @@
     <string name="menu_space_shortcut_label" msgid="2410328639272162537">"espace"</string>
     <string name="menu_enter_shortcut_label" msgid="2743362785111309668">"entrée"</string>
     <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"suppr"</string>
-    <string name="search_go" msgid="8298016669822141719">"Recherche"</string>
+    <string name="search_go" msgid="8298016669822141719">"Rechercher"</string>
     <string name="search_hint" msgid="1733947260773056054">"Recherche en cours..."</string>
-    <string name="searchview_description_search" msgid="6749826639098512120">"Recherche"</string>
+    <string name="searchview_description_search" msgid="6749826639098512120">"Rechercher"</string>
     <string name="searchview_description_query" msgid="5911778593125355124">"Requête de recherche"</string>
     <string name="searchview_description_clear" msgid="1330281990951833033">"Effacer la requête"</string>
     <string name="searchview_description_submit" msgid="2688450133297983542">"Envoyer la requête"</string>
@@ -1252,7 +1252,7 @@
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Appuyer deux fois pour régler le zoom"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Impossible d\'ajouter le widget."</string>
     <string name="ime_action_go" msgid="8320845651737369027">"Aller"</string>
-    <string name="ime_action_search" msgid="658110271822807811">"Recherche"</string>
+    <string name="ime_action_search" msgid="658110271822807811">"Rechercher"</string>
     <string name="ime_action_send" msgid="2316166556349314424">"Envoyer"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"Suivante"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"Terminé"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index cad323e..9f2dcd3 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1152,7 +1152,7 @@
     <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"कभी भी अनुमति न दें"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"सिमकार्ड निकाला गया"</string>
     <string name="sim_removed_message" msgid="2333164559970958645">"मान्‍य सि‍म कार्ड डालकर पुन: प्रारंभ करने तक मोबाइल नेटवर्क अनुपलब्‍ध रहेगा."</string>
-    <string name="sim_done_button" msgid="827949989369963775">"पूर्ण"</string>
+    <string name="sim_done_button" msgid="827949989369963775">"हो गया"</string>
     <string name="sim_added_title" msgid="3719670512889674693">"सिम कार्ड जोड़ा गया"</string>
     <string name="sim_added_message" msgid="6599945301141050216">"मोबाइल नेटवर्क की पहुंच पाने लिए अपना डिवाइस फिर से चालू करें."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"फिर से शुरू करें"</string>
@@ -1164,7 +1164,7 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"समय सेट करें"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"तारीख सेट करें"</string>
     <string name="date_time_set" msgid="5777075614321087758">"सेट करें"</string>
-    <string name="date_time_done" msgid="2507683751759308828">"पूर्ण"</string>
+    <string name="date_time_done" msgid="2507683751759308828">"हो गया"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"नया: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"<xliff:g id="APP_NAME">%1$s</xliff:g> द्वारा प्रदत्त."</string>
     <string name="no_permissions" msgid="7283357728219338112">"किसी अनुमति की आवश्‍यकता नहीं है"</string>
@@ -1176,7 +1176,7 @@
     <string name="usb_ptp_notification_title" msgid="1347328437083192112">"फ़ोटो स्‍थानांतरण के लिए USB"</string>
     <string name="usb_midi_notification_title" msgid="4850904915889144654">"MIDI के लिए USB"</string>
     <string name="usb_accessory_notification_title" msgid="7848236974087653666">"USB सहायक सामग्री से कनेक्‍ट कि‍या गया"</string>
-    <string name="usb_notification_message" msgid="3370903770828407960">"अधिक विकल्पों के लिए टैप करें."</string>
+    <string name="usb_notification_message" msgid="3370903770828407960">"ज़्यादा विकल्पों के लिए टैप करें."</string>
     <string name="usb_unsupported_audio_accessory_title" msgid="3529881374464628084">"एनालॉग ऑडियो एक्सेसरी का पता चला"</string>
     <string name="usb_unsupported_audio_accessory_message" msgid="6309553946441565215">"अटैच किया गया डिवाइस इस फ़ोन से संगत नहीं है. अधिक जानने के लिए टैप करें."</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB डीबग कनेक्ट किया गया"</string>
@@ -1255,7 +1255,7 @@
     <string name="ime_action_search" msgid="658110271822807811">"सर्च करें"</string>
     <string name="ime_action_send" msgid="2316166556349314424">"भेजें"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"आगे"</string>
-    <string name="ime_action_done" msgid="8971516117910934605">"पूर्ण"</string>
+    <string name="ime_action_done" msgid="8971516117910934605">"हो गया"</string>
     <string name="ime_action_previous" msgid="1443550039250105948">"पीछे जाएं"</string>
     <string name="ime_action_default" msgid="2840921885558045721">"निष्‍पादित करें"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"<xliff:g id="NUMBER">%s</xliff:g> के उपयोग द्वारा \n नंबर डायल करें"</string>
@@ -1297,14 +1297,14 @@
     <string name="tethered_notification_message" msgid="2113628520792055377">"सेट करने के लिए टैप करें."</string>
     <string name="back_button_label" msgid="2300470004503343439">"वापस जाएं"</string>
     <string name="next_button_label" msgid="1080555104677992408">"आगे"</string>
-    <string name="skip_button_label" msgid="1275362299471631819">"रद्द करें"</string>
+    <string name="skip_button_label" msgid="1275362299471631819">"अभी नहीं"</string>
     <string name="no_matches" msgid="8129421908915840737">"कोई मिलान नहीं"</string>
     <string name="find_on_page" msgid="1946799233822820384">"पेज पर ढूंढें"</string>
     <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
       <item quantity="one"><xliff:g id="TOTAL">%d</xliff:g> में से <xliff:g id="INDEX">%d</xliff:g></item>
       <item quantity="other"><xliff:g id="TOTAL">%d</xliff:g> में से <xliff:g id="INDEX">%d</xliff:g></item>
     </plurals>
-    <string name="action_mode_done" msgid="7217581640461922289">"पूर्ण"</string>
+    <string name="action_mode_done" msgid="7217581640461922289">"हो गया"</string>
     <string name="progress_erasing" product="nosdcard" msgid="4521573321524340058">"USB मेमोरी मिटाया जा रहा है…"</string>
     <string name="progress_erasing" product="default" msgid="6596988875507043042">"SD कार्ड मिटाया जा रहा है…"</string>
     <string name="share" msgid="1778686618230011964">"साझा करें"</string>
@@ -1346,7 +1346,7 @@
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"रद्द करें"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"मिटाएं"</string>
-    <string name="keyboardview_keycode_done" msgid="1992571118466679775">"पूर्ण"</string>
+    <string name="keyboardview_keycode_done" msgid="1992571118466679775">"हो गया"</string>
     <string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"Mode change"</string>
     <string name="keyboardview_keycode_shift" msgid="2270748814315147690">"Shift"</string>
     <string name="keyboardview_keycode_enter" msgid="2985864015076059467">"Enter"</string>
@@ -1479,7 +1479,7 @@
     <string name="accessibility_shortcut_disabling_service" msgid="2747243438223109821">"सुलभता शॉर्टकट ने <xliff:g id="SERVICE_NAME">%1$s</xliff:g> को बंद किया"</string>
     <string name="accessibility_button_prompt_text" msgid="4234556536456854251">"सुलभता बटन पर टैप करते समय इस्तेमाल की जाने वाली सुविधा चुनें:"</string>
     <string name="accessibility_button_instructional_text" msgid="6942300463612999993">"सुविधाओं में बदलाव करने के लिए, सुलभता बटन को दबाकर रखें."</string>
-    <string name="accessibility_magnification_chooser_text" msgid="1227146738764986237">"आवर्धन"</string>
+    <string name="accessibility_magnification_chooser_text" msgid="1227146738764986237">"बड़ा करें"</string>
     <string name="user_switched" msgid="3768006783166984410">"मौजूदा उपयोगकर्ता <xliff:g id="NAME">%1$s</xliff:g>."</string>
     <string name="user_switching_message" msgid="2871009331809089783">"<xliff:g id="NAME">%1$s</xliff:g> पर स्विच किया जा रहा है…"</string>
     <string name="user_logging_out_message" msgid="8939524935808875155">"<xliff:g id="NAME">%1$s</xliff:g> द्वारा प्रस्‍थान किया जा रहा है…"</string>
@@ -1594,7 +1594,7 @@
     <string name="immersive_cling_title" msgid="8394201622932303336">"पूरे स्क्रीन पर देखें"</string>
     <string name="immersive_cling_description" msgid="3482371193207536040">"बाहर निकलने के लिए, ऊपर से नीचे स्वा‍इप करें."</string>
     <string name="immersive_cling_positive" msgid="5016839404568297683">"ठीक है"</string>
-    <string name="done_label" msgid="2093726099505892398">"पूर्ण"</string>
+    <string name="done_label" msgid="2093726099505892398">"हो गया"</string>
     <string name="hour_picker_description" msgid="6698199186859736512">"घंटो का चक्राकार स्लाइडर"</string>
     <string name="minute_picker_description" msgid="8606010966873791190">"मिनटों का चक्राकार स्लाइडर"</string>
     <string name="select_hours" msgid="6043079511766008245">"घंटे चुनें"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index e8b5ed5..6806e75 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -265,7 +265,7 @@
     <string name="permgroupdesc_calendar" msgid="3889615280211184106">"캘린더에 액세스"</string>
     <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="4656988620100940350">"SMS 메시지 전송 및 보기"</string>
-    <string name="permgrouplab_storage" msgid="1971118770546336966">"저장"</string>
+    <string name="permgrouplab_storage" msgid="1971118770546336966">"저장용량"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"기기 사진, 미디어, 파일 액세스"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"마이크"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"오디오 녹음"</string>
diff --git a/core/res/res/values-mcc302-mnc370-sk/strings.xml b/core/res/res/values-mcc302-mnc370-sk/strings.xml
index b93949e..6a3e8c7 100644
--- a/core/res/res/values-mcc302-mnc370-sk/strings.xml
+++ b/core/res/res/values-mcc302-mnc370-sk/strings.xml
@@ -21,6 +21,6 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
   <string-array name="wfcSpnFormats">
     <item msgid="5022384999749536798">"%s"</item>
-    <item msgid="8117276330682171665">"%s Wi-Fi"</item>
+    <item msgid="8117276330682171665">"%s Wi‑Fi"</item>
   </string-array>
 </resources>
diff --git a/core/res/res/values-mcc302-mnc720-sk/strings.xml b/core/res/res/values-mcc302-mnc720-sk/strings.xml
index 9b2336d..e7411be 100644
--- a/core/res/res/values-mcc302-mnc720-sk/strings.xml
+++ b/core/res/res/values-mcc302-mnc720-sk/strings.xml
@@ -21,6 +21,6 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
   <string-array name="wfcSpnFormats">
     <item msgid="2776657861851140021">"%s"</item>
-    <item msgid="5094669985484060934">"%s Wi-Fi"</item>
+    <item msgid="5094669985484060934">"%s Wi‑Fi"</item>
   </string-array>
 </resources>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 31af989..ef66f2b 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -172,10 +172,10 @@
     <string name="work_profile_deleted_description" msgid="1100529432509639864">"प्रशासक अॅप गहाळ असल्यामुळे कार्य प्रोफाइल हटवले गेले"</string>
     <string name="work_profile_deleted_details" msgid="6307630639269092360">"कार्य प्रोफाइल प्रशासक अॅप गहाळ आहे किंवा करप्ट आहे. परिणामी, आपले कार्य प्रोफाइल आणि संबंधित डेटा हटवले गेले आहेत. सहाय्यासाठी आपल्या प्रशासकाशी संपर्क साधा."</string>
     <string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"आपले कार्य प्रोफाइल आता या डिव्हाइसवर उपलब्‍ध नाही"</string>
-    <string name="network_logging_notification_title" msgid="6399790108123704477">"डीव्हाइस व्यवस्थापित केले आहे"</string>
-    <string name="network_logging_notification_text" msgid="7930089249949354026">"आपली संस्था हे डीव्हाइस व्यवस्थापित करते आणि नेटवर्क रहदारीचे निरीक्षण करू शकते. तपशीलांसाठी टॅप करा."</string>
-    <string name="factory_reset_warning" msgid="5423253125642394387">"तुमचे डीव्हाइस मिटविले जाईल"</string>
-    <string name="factory_reset_message" msgid="7972496262232832457">"हे प्रशासक अ‍ॅप वापरले जाऊ शकत नाही. तुमचे डीव्हाइस आता मिटवले जाईल.\n\nतुम्हाला प्रश्न असल्यास, तुमच्या संस्थेच्या प्रशासकाशी संपर्क साधा."</string>
+    <string name="network_logging_notification_title" msgid="6399790108123704477">"डिव्हाइस व्यवस्थापित केले आहे"</string>
+    <string name="network_logging_notification_text" msgid="7930089249949354026">"आपली संस्था हे डिव्हाइस व्यवस्थापित करते आणि नेटवर्क रहदारीचे निरीक्षण करू शकते. तपशीलांसाठी टॅप करा."</string>
+    <string name="factory_reset_warning" msgid="5423253125642394387">"तुमचे डिव्हाइस मिटविले जाईल"</string>
+    <string name="factory_reset_message" msgid="7972496262232832457">"हे प्रशासक अ‍ॅप वापरले जाऊ शकत नाही. तुमचे डिव्हाइस आता मिटवले जाईल.\n\nतुम्हाला प्रश्न असल्यास, तुमच्या संस्थेच्या प्रशासकाशी संपर्क साधा."</string>
     <string name="me" msgid="6545696007631404292">"मी"</string>
     <string name="power_dialog" product="tablet" msgid="8545351420865202853">"टॅबलेट पर्याय"</string>
     <string name="power_dialog" product="tv" msgid="6153888706430556356">"टीव्ही पर्याय"</string>
@@ -212,11 +212,11 @@
     <string name="global_action_emergency" msgid="7112311161137421166">"आणीबाणी"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"बग रीपोर्ट"</string>
     <string name="bugreport_title" msgid="2667494803742548533">"बग रीपोर्ट घ्या"</string>
-    <string name="bugreport_message" msgid="398447048750350456">"ई-मेल संदेश म्हणून पाठविण्यासाठी, हे तुमच्या सद्य डीव्हाइस स्थितीविषयी माहिती संकलित करेल. बग रीपोर्ट सुरू करण्यापासून तो पाठविण्यापर्यंत थोडा वेळ लागेल; कृपया धीर धरा."</string>
+    <string name="bugreport_message" msgid="398447048750350456">"ई-मेल संदेश म्हणून पाठविण्यासाठी, हे तुमच्या सद्य डिव्हाइस स्थितीविषयी माहिती संकलित करेल. बग रीपोर्ट सुरू करण्यापासून तो पाठविण्यापर्यंत थोडा वेळ लागेल; कृपया धीर धरा."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"परस्परसंवादी अहवाल"</string>
     <string name="bugreport_option_interactive_summary" msgid="229299488536107968">"बहुतांश प्रसंगांमध्ये याचा वापर करा. ते आपल्याला अहवालाच्या प्रगतीचा मागोवा घेण्याची, समस्येविषयी आणखी तपाशील प्रविष्ट करण्याची आणि स्क्रीनशॉट घेण्याची अनुमती देते. ते कदाचित अहवाल देण्यासाठी बराच वेळ घेणारे कमी-वापरलेले विभाग वगळू शकते."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"संपूर्ण अहवाल"</string>
-    <string name="bugreport_option_full_summary" msgid="7210859858969115745">"तुमचे डीव्हाइस प्रतिसाद देत नाही किंवा खूप धीमे असते किंवा तुम्हाला सर्व अहवाल विभागांची आवश्यकता असते तेव्हा कमीतकमी सिस्टम हस्तक्षेपासाठी या पर्यायाचा वापर करा. तुम्हाला आणखी तपशील एंटर करण्याची किंवा अतिरिक्त स्क्रीनशॉट घेण्याची अनुमती देत नाही."</string>
+    <string name="bugreport_option_full_summary" msgid="7210859858969115745">"तुमचे डिव्हाइस प्रतिसाद देत नाही किंवा खूप धीमे असते किंवा तुम्हाला सर्व अहवाल विभागांची आवश्यकता असते तेव्हा कमीतकमी सिस्टम हस्तक्षेपासाठी या पर्यायाचा वापर करा. तुम्हाला आणखी तपशील एंटर करण्याची किंवा अतिरिक्त स्क्रीनशॉट घेण्याची अनुमती देत नाही."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
       <item quantity="one">दोष अहवालासाठी <xliff:g id="NUMBER_1">%d</xliff:g> सेकंदामध्‍ये स्क्रीनशॉट घेत आहे.</item>
       <item quantity="other">दोष अहवालासाठी <xliff:g id="NUMBER_1">%d</xliff:g> सेकंदांमध्‍ये स्क्रीनशॉट घेत आहे.</item>
@@ -244,7 +244,7 @@
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"नेटवर्क सूचना"</string>
     <string name="notification_channel_network_available" msgid="4531717914138179517">"नेटवर्क उपलब्ध"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN स्थिती"</string>
-    <string name="notification_channel_device_admin" msgid="1568154104368069249">"डीव्हाइस प्रशासन"</string>
+    <string name="notification_channel_device_admin" msgid="1568154104368069249">"डिव्हाइस प्रशासन"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"सूचना"</string>
     <string name="notification_channel_retail_mode" msgid="6088920674914038779">"रीटेल डेमो"</string>
     <string name="notification_channel_usb" msgid="9006850475328924681">"USB कनेक्‍शन"</string>
@@ -266,7 +266,7 @@
     <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="4656988620100940350">"SMS संदेश पाठवणे आणि पाहणे हे"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"संचयन"</string>
-    <string name="permgroupdesc_storage" msgid="637758554581589203">"तुमच्या डीव्हाइस वरील फोटो, मीडिया आणि फायलींमध्‍ये अॅक्सेस"</string>
+    <string name="permgroupdesc_storage" msgid="637758554581589203">"तुमच्या डिव्हाइस वरील फोटो, मीडिया आणि फायलींमध्‍ये अॅक्सेस"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"मायक्रोफोन"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ऑडिओ रेकॉर्ड"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"कॅमेरा"</string>
@@ -288,7 +288,7 @@
     <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"फिंगरप्रिंट जेश्चर"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"डिव्‍हाइसच्‍या फिंगरप्रिंट सेंसरवर केलेले जेश्चर कॅप्‍चर करू शकते."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"स्टेटस बार अक्षम करा किंवा सुधारित करा"</string>
-    <string name="permdesc_statusBar" msgid="8434669549504290975">"स्टेटस बार अक्षम करण्यासाठी किंवा सिस्टीम चिन्हे जोडण्यासाठी आणि काढण्यासाठी अॅप ला अनुमती देते."</string>
+    <string name="permdesc_statusBar" msgid="8434669549504290975">"स्टेटस बार अक्षम करण्यासाठी किंवा सिस्टम चिन्हे जोडण्यासाठी आणि काढण्यासाठी अॅप ला अनुमती देते."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"स्टेटस बार होऊ द्या"</string>
     <string name="permdesc_statusBarService" msgid="716113660795976060">"स्टेटस बार होण्यासाठी अॅप ला अनुमती देते."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"स्‍टेटस बार विस्तृत करा/संकुचित करा"</string>
@@ -319,8 +319,8 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"WAP संदेश प्राप्त करण्यास आणि त्यावर प्रक्रिया करण्यासाठी अॅप ला अनुमती देते. ही परवानगी आपल्याला पाठविलेले संदेश आपल्याला न दर्शविता त्यांचे परीक्षण करण्याची आणि ते हटविण्याची क्षमता समाविष्ट करते."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"चालणारे अॅप्स पुनर्प्राप्त करा"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"सध्या आणि अलीकडे चालणार्‍या कार्यांविषयी माहिती पुनर्प्राप्त करण्यासाठी अॅप ला अनुमती देते. हे डिव्हाइसवर कोणते अॅप्लिकेशन वापरले जात आहेत त्याविषयी माहिती शोधण्यासाठी अॅप ला अनुमती देऊ शकतात."</string>
-    <string name="permlab_manageProfileAndDeviceOwners" msgid="7918181259098220004">"प्रोफाईल आणि डीव्हाइस मालक व्यवस्थापित करा"</string>
-    <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"प्रोफाईल मालक आणि डीव्हाइस मालक सेट करण्याची अॅप्सना अनुमती द्या."</string>
+    <string name="permlab_manageProfileAndDeviceOwners" msgid="7918181259098220004">"प्रोफाईल आणि डिव्हाइस मालक व्यवस्थापित करा"</string>
+    <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"प्रोफाईल मालक आणि डिव्हाइस मालक सेट करण्याची अॅप्सना अनुमती द्या."</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"चालणारे अॅप्स पुनर्क्रमित करा"</string>
     <string name="permdesc_reorderTasks" msgid="7734217754877439351">"समोर आणि पार्श्वभूमीवर कार्ये हलविण्यासाठी अॅप ला अनुमती देते. अॅप हे आपल्या इनपुटशिवाय करू शकतो."</string>
     <string name="permlab_enableCarMode" msgid="5684504058192921098">"कार मोड सक्षम करा"</string>
@@ -342,9 +342,9 @@
     <string name="permlab_writeSettings" msgid="2226195290955224730">"सिस्टम सेटिंग्ज सुधारित करा"</string>
     <string name="permdesc_writeSettings" msgid="7775723441558907181">"सिस्टीमचा सेटिंग्ज डेटा सुधारित करण्यासाठी अॅप ला अनुमती देते. दुर्भावनापूर्ण अॅप्स आपल्या सिस्टीमचे कॉन्फिगरेशन दूषित करू शकतात."</string>
     <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"सुरूवातीस चालवा"</string>
-    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"जसे सिस्टीम बूट करणे समाप्त करते तसे अॅप ला स्वतः प्रारंभ करण्यास अनुमती देते. यामुळे टॅबलेट प्रारंभ करण्यास वेळ लागू शकतो आणि नेहमी चालू राहून एकंदर टॅबलेटला धीमे करण्यास अॅप ला अनुमती देते."</string>
-    <string name="permdesc_receiveBootCompleted" product="tv" msgid="4525890122209673621">"सिस्टीम बूट करणे समाप्त करते तसेच अॅपने स्वतः प्रारंभ करण्यास त्याला अनुमती देते. यामुळे टीव्ही प्रारंभ करण्यासाठी त्यास जास्त वेळ लागू शकतो आणि नेहमी चालू ठेवून संपूर्ण टॅबलेट धीमे करण्यासाठी अॅपला अनुमती देते."</string>
-    <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"जसे सिस्टीम बूट करणे समाप्त करते तसे अॅप ला स्वतः प्रारंभ करण्यास अनुमती देते. यामुळे फोन प्रारंभ करण्यास वेळ लागू शकतो आणि नेहमी चालू राहून एकंदर फोनला धीमे करण्यास अॅप ला अनुमती देते."</string>
+    <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"जसे सिस्टम बूट करणे समाप्त करते तसे अॅप ला स्वतः प्रारंभ करण्यास अनुमती देते. यामुळे टॅबलेट प्रारंभ करण्यास वेळ लागू शकतो आणि नेहमी चालू राहून एकंदर टॅबलेटला धीमे करण्यास अॅप ला अनुमती देते."</string>
+    <string name="permdesc_receiveBootCompleted" product="tv" msgid="4525890122209673621">"सिस्टम बूट करणे समाप्त करते तसेच अॅपने स्वतः प्रारंभ करण्यास त्याला अनुमती देते. यामुळे टीव्ही प्रारंभ करण्यासाठी त्यास जास्त वेळ लागू शकतो आणि नेहमी चालू ठेवून संपूर्ण टॅबलेट धीमे करण्यासाठी अॅपला अनुमती देते."</string>
+    <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"जसे सिस्टम बूट करणे समाप्त करते तसे अॅप ला स्वतः प्रारंभ करण्यास अनुमती देते. यामुळे फोन प्रारंभ करण्यास वेळ लागू शकतो आणि नेहमी चालू राहून एकंदर फोनला धीमे करण्यास अॅप ला अनुमती देते."</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"रोचक प्रसारण पाठवा"</string>
     <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"रोचक प्रसारणे पाठविण्यासाठी अॅप ला अनुमती देते, जे प्रसारण समाप्त झाल्यानंतर देखील तसेच राहते. अत्याधिक वापरामुळे बरीच मेमरी वापरली जाऊन तो टॅब्लेटला धीमा किंवा अस्थिर करू शकतो."</string>
     <string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"रोचक प्रसारणे पाठविण्यास अॅपला अनुमती देते, जे प्रसारण समाप्त झाल्यानंतर तसेच रहाते. अतिरिक्त वापर टीव्ही धीमा किंवा यासाठी बरीच मेमरी वापरली जात असल्यामुळे तो अस्थिर करू शकतो."</string>
@@ -396,7 +396,7 @@
     <string name="permlab_accessImsCallService" msgid="3574943847181793918">"IMS कॉल सेवा अॅक्सेस करा"</string>
     <string name="permdesc_accessImsCallService" msgid="8992884015198298775">"आपल्‍या हस्तक्षेपाशिवाय अ‍ॅपला कॉल करण्‍यासाठी IMS सेवा वापरण्याची अनुमती देते."</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"फोन स्थिती आणि ओळख वाचा"</string>
-    <string name="permdesc_readPhoneState" msgid="1639212771826125528">"डीव्हाइस च्या फोन वैशिष्ट्यांवर अॅक्सेस करण्यास अॅपला अनुमती देते. ही परवानगी कॉल अॅक्टिव्हेट असला किंवा नसला तरीही, फोन नंबर आणि डीव्हाइस आयडी आणि कॉलद्वारे कनेक्ट केलेला रीमोट नंबर निर्धारित करण्यासाठी अॅपला अनुमती देते."</string>
+    <string name="permdesc_readPhoneState" msgid="1639212771826125528">"डिव्हाइस च्या फोन वैशिष्ट्यांवर अॅक्सेस करण्यास अॅपला अनुमती देते. ही परवानगी कॉल अॅक्टिव्हेट असला किंवा नसला तरीही, फोन नंबर आणि डिव्हाइस आयडी आणि कॉलद्वारे कनेक्ट केलेला रीमोट नंबर निर्धारित करण्यासाठी अॅपला अनुमती देते."</string>
     <string name="permlab_manageOwnCalls" msgid="1503034913274622244">"प्रणालीच्या माध्यमातून कॉल रूट करा"</string>
     <string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"कॉल करण्याचा अनुभव सुधारण्यासाठी अॅपला त्याचे कॉल प्रणालीच्या माध्यमातून रूट करू देते."</string>
     <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"फोन नंबर वाचा"</string>
@@ -412,9 +412,9 @@
     <string name="permdesc_transmitIr" product="tv" msgid="3926790828514867101">"टीव्हीचे इन्फ्रारेड ट्रान्समीटर वापरण्यासाठी अॅपला अनुमती देते."</string>
     <string name="permdesc_transmitIr" product="default" msgid="7957763745020300725">"अ‍ॅप ला फोनच्‍या इन्‍फ्रारेड ट्रान्‍समीटरचा वापर करण्‍याची अनुमती देते."</string>
     <string name="permlab_setWallpaper" msgid="6627192333373465143">"वॉलपेपर सेट करा"</string>
-    <string name="permdesc_setWallpaper" msgid="7373447920977624745">"सिस्टीम वॉलपेपर सेट करण्यासाठी अॅप ला अनुमती देते."</string>
+    <string name="permdesc_setWallpaper" msgid="7373447920977624745">"सिस्टम वॉलपेपर सेट करण्यासाठी अॅप ला अनुमती देते."</string>
     <string name="permlab_setWallpaperHints" msgid="3278608165977736538">"आपला वॉलपेपर आकार समायोजित करा"</string>
-    <string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"सिस्टीम वॉलपेपर आकार सूचना सेट करण्यासाठी अॅप ला अनुमती देते."</string>
+    <string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"सिस्टम वॉलपेपर आकार सूचना सेट करण्यासाठी अॅप ला अनुमती देते."</string>
     <string name="permlab_setTimeZone" msgid="2945079801013077340">"टाइम झोन सेट करा"</string>
     <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"टॅब्लेटचा टाइम झोन बदलण्यासाठी अॅप ला अनुमती देते."</string>
     <string name="permdesc_setTimeZone" product="tv" msgid="888864653946175955">"टीव्हीचा टाईम झोन बदलण्यासाठी अॅपला अनुमती देते."</string>
@@ -434,15 +434,15 @@
     <string name="permlab_accessWifiState" msgid="5202012949247040011">"वाय-फाय कनेक्शन पहा"</string>
     <string name="permdesc_accessWifiState" msgid="5002798077387803726">"वाय-फाय सक्षम केले आहे किंवा नाही आणि कनेक्ट केलेल्या वाय-फाय डीव्हाइसचे नाव यासारख्या, वाय-फाय नेटवर्किंग विषयीची माहिती पाहण्यासाठी अॅप ला अनुमती देते."</string>
     <string name="permlab_changeWifiState" msgid="6550641188749128035">"वाय-फाय वरून कनेक्ट करा आणि डिस्कनेक्ट करा"</string>
-    <string name="permdesc_changeWifiState" msgid="7137950297386127533">"वाय-फाय अॅक्सेस बिंदूंवर कनेक्ट करण्यासाठी आणि त्यावरून डिस्कनेक्ट करण्यासाठी आणि वाय-फाय नेटवर्कसाठी डीव्हाइस कॉंफिगरेशनमध्ये बदल करण्यासाठी अॅपला अनुमती देते."</string>
+    <string name="permdesc_changeWifiState" msgid="7137950297386127533">"वाय-फाय अॅक्सेस बिंदूंवर कनेक्ट करण्यासाठी आणि त्यावरून डिस्कनेक्ट करण्यासाठी आणि वाय-फाय नेटवर्कसाठी डिव्हाइस कॉंफिगरेशनमध्ये बदल करण्यासाठी अॅपला अनुमती देते."</string>
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"वाय-फाय मल्‍टिकास्‍ट रिसेप्‍शनला अनुमती द्या"</string>
     <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"मल्टिकास्ट पत्ते वापरून फक्त तुमच्या टॅब्लेटवर नाही, तर वाय-फाय नेटवर्कवरील सर्व डीव्हाइसवर पाठविलेले पॅकेट प्राप्त करण्यासाठी अॅप ला अनुमती देते. हे मल्टिकास्टखेरिज इतर मोडसाठी अधिक पॉवर वापरते."</string>
     <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"केवळ आपला टीव्ही न वापरता, एकाधिक पत्ते वापरून एका वाय-फाय नेटवकवरील सर्व डीव्हाइसवर पाठविलेली पॅकेट प्राप्त करण्यासाठी अॅपला अनुमती देते."</string>
     <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"मल्टिकास्ट पत्ते वापरून फक्त तुमच्या फोनवर नाही, तर वाय-फाय नेटवर्कवरील सर्व डीव्हाइसवर पाठविलेले पॅकेट प्राप्त करण्यासाठी अॅप ला अनुमती देते. हे मल्टिकास्टखेरिज इतर मोडसाठी अधिक पॉवर वापरते."</string>
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"ब्लूटूथ सेटिंग्ज अॅक्सेस करा"</string>
-    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"स्थानिक ब्लूटूथ टॅबलेट कॉंफिगर करण्याकरिता आणि दूरस्थ डीव्हाइस शोधण्यासाठी आणि त्यासह जोडण्यासाठी अॅप ला अनुमती देते."</string>
+    <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"स्थानिक ब्लूटूथ टॅबलेट कॉंफिगर करण्याकरिता आणि दूरस्थ डिव्हाइस शोधण्यासाठी आणि त्यासह जोडण्यासाठी अॅप ला अनुमती देते."</string>
     <string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"स्थानिक ब्लूटूथ टीव्ही कॉंफिगर करण्यासाठी आणि दूरस्थ डीव्हाइससह शोधण्यासाठी आणि जोडण्यासाठी अॅपला अनुमती देते."</string>
-    <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"स्थानिक ब्लूटूथ फोन कॉंफिगर करण्याकरिता आणि दूरस्थ डीव्हाइस शोधण्यासाठी आणि त्यासह जोडण्यासाठी अॅप ला अनुमती देते."</string>
+    <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"स्थानिक ब्लूटूथ फोन कॉंफिगर करण्याकरिता आणि दूरस्थ डिव्हाइस शोधण्यासाठी आणि त्यासह जोडण्यासाठी अॅप ला अनुमती देते."</string>
     <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAX कनेक्ट करा आणि त्यावरून डिस्कनेक्ट करा"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"WiMAX सक्षम केले आहे किंवा नाही आणि कनेक्ट केलेल्या कोणत्याही WiMAX नेटवर्क विषयीची माहिती निर्धारित करण्यासाठी अॅप ला अनुमती देते."</string>
     <string name="permlab_changeWimaxState" msgid="340465839241528618">"WiMAX स्थिती बदला"</string>
@@ -525,7 +525,7 @@
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"होल्‍डरला वाहकद्वारे-प्रदान केलेल्या कॉन्फिगरेशन अ‍ॅपची विनंती करण्‍याची अनुमती देते. सामान्‍य अ‍ॅप्‍ससाठी कधीही आवश्‍यक नसावे."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"नेटवर्क स्‍थितींवरील निरीक्षणांसाठी ऐका"</string>
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"अनु्प्रयोगाला नेटवर्क स्‍थितींवरील निरीक्षणे ऐकण्‍यासाठी अनुमती देते. सामान्‍य अ‍ॅप्‍ससाठी कधीही आवश्‍यक नसावे."</string>
-    <string name="permlab_setInputCalibration" msgid="4902620118878467615">"इनपुट डीव्हाइस कॅलिब्रेशन बदला"</string>
+    <string name="permlab_setInputCalibration" msgid="4902620118878467615">"इनपुट डिव्हाइस कॅलिब्रेशन बदला"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"स्पर्श स्क्रीनची कॅलिब्रेशन प्राचले सुधारित करण्यासाठी अॅप ला अनुमती देते. सामान्य अॅप्स साठी कधीही आवश्यक नसते."</string>
     <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM प्रमाणपत्रे अॅक्सेस करा"</string>
     <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"DRM प्रमाणपत्रांची तरतूद करण्यासाठी आणि वापरण्यासाठी अनुप्रयोगास अनुमती देते. सामान्य अॅप्सकरिता कधीही आवश्यकता नसते."</string>
@@ -560,14 +560,14 @@
     <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="6336255514635308054">"कोणत्याही चेतावणी शिवाय या वापरकर्त्याचा या टॅब्लेटवरील डेटा मिटवा."</string>
     <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"कोणत्याही चेतावणी शिवाय या वापरकर्त्याचा या टीव्ही वरील डेटा मिटवा."</string>
     <string name="policydesc_wipeData_secondaryUser" product="default" msgid="6787904546711590238">"कोणत्याही चेतावणी शिवाय या वापरकर्त्याचा या फोनवरील डेटा मिटवा."</string>
-    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"डीव्हाइस समग्र प्रॉक्सी सेट करा"</string>
-    <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"धोरण सक्षम असताना वापरण्यासाठी डीव्हाइस समग्र प्रॉक्सी सेट करा. फक्त डीव्हाइस मालक समग्र प्रॉक्सी सेट करु शकतो."</string>
+    <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"डिव्हाइस समग्र प्रॉक्सी सेट करा"</string>
+    <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"धोरण सक्षम असताना वापरण्यासाठी डिव्हाइस समग्र प्रॉक्सी सेट करा. फक्त डिव्हाइस मालक समग्र प्रॉक्सी सेट करु शकतो."</string>
     <string name="policylab_expirePassword" msgid="5610055012328825874">"स्क्रीन लॉक संकेतशब्द कालबाह्यता सेट करा"</string>
     <string name="policydesc_expirePassword" msgid="5367525762204416046">"लॉक-स्क्रीन संकेतशब्द किती वारंवार बदलणे आवश्यक आहे ते बदला."</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"स्टोरेज एंक्रिप्शन सेट करा"</string>
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"स्टोअर केलेला अॅप डेटा एंक्रिप्ट केला जाणे आवश्यक आहे."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"कॅमेरे अक्षम करा"</string>
-    <string name="policydesc_disableCamera" msgid="2306349042834754597">"सर्व डीव्हाइस कॅमेर्‍यांचा वापर प्रतिबंधित करा."</string>
+    <string name="policydesc_disableCamera" msgid="2306349042834754597">"सर्व डिव्हाइस कॅमेर्‍यांचा वापर प्रतिबंधित करा."</string>
     <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"काही स्क्रीन लॉक वैशिष्‍ट्ये अक्षम करा"</string>
     <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"काही स्क्रीन लॉक वैशिष्‍ट्यांचा वापर प्रतिबंधित करा."</string>
   <string-array name="phoneTypes">
@@ -1006,7 +1006,7 @@
     <string name="whichImageCaptureApplicationLabel" msgid="6390303445371527066">"इमेज कॅप्चर करा"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"या क्रियेसाठी डीफॉल्‍टनुसार वापरा."</string>
     <string name="use_a_different_app" msgid="8134926230585710243">"एक भिन्न अ‍ॅप वापरा"</string>
-    <string name="clearDefaultHintMsg" msgid="3252584689512077257">"डाउनलोड केलेल्या सिस्टीम सेटिंग्ज &gt; Apps &gt; मधील डीफॉल्ट साफ करा."</string>
+    <string name="clearDefaultHintMsg" msgid="3252584689512077257">"डाउनलोड केलेल्या सिस्टम सेटिंग्ज &gt; Apps &gt; मधील डीफॉल्ट साफ करा."</string>
     <string name="chooseActivity" msgid="7486876147751803333">"क्रिया निवडा"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB डिव्हाइससाठी अॅप निवडा"</string>
     <string name="noApplications" msgid="2991814273936504689">"कोणतेही अॅप्स ही क्रिया करू शकत नाहीत."</string>
@@ -1017,7 +1017,7 @@
     <string name="aerr_restart" msgid="7581308074153624475">"अॅप पुन्हा उघडा"</string>
     <string name="aerr_report" msgid="5371800241488400617">"अभिप्राय पाठवा"</string>
     <string name="aerr_close" msgid="2991640326563991340">"बंद करा"</string>
-    <string name="aerr_mute" msgid="1974781923723235953">"डीव्हाइस रीस्टार्ट होईपर्यंत म्युट करा"</string>
+    <string name="aerr_mute" msgid="1974781923723235953">"डिव्हाइस रीस्टार्ट होईपर्यंत म्युट करा"</string>
     <string name="aerr_wait" msgid="3199956902437040261">"प्रतीक्षा करा"</string>
     <string name="aerr_close_app" msgid="3269334853724920302">"अॅप बंद करा"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
@@ -1034,7 +1034,7 @@
     <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> मूळतः लाँच केले."</string>
     <string name="screen_compat_mode_scale" msgid="3202955667675944499">"स्केल"</string>
     <string name="screen_compat_mode_show" msgid="4013878876486655892">"नेहमी दर्शवा"</string>
-    <string name="screen_compat_mode_hint" msgid="1064524084543304459">"सिस्टीम सेटिंग्ज &gt; Apps &gt; डाउनलोड केलेले मध्ये हे पुन्हा-सक्षम करा."</string>
+    <string name="screen_compat_mode_hint" msgid="1064524084543304459">"सिस्टम सेटिंग्ज &gt; Apps &gt; डाउनलोड केलेले मध्ये हे पुन्हा-सक्षम करा."</string>
     <string name="unsupported_display_size_message" msgid="6545327290756295232">"<xliff:g id="APP_NAME">%1$s</xliff:g> वर्तमान डिस्प्ले आकार सेटिंगला समर्थन देत नाही आणि अनपेक्षित वर्तन करू शकते."</string>
     <string name="unsupported_display_size_show" msgid="7969129195360353041">"नेहमी दर्शवा"</string>
     <string name="smv_application" msgid="3307209192155442829">"अॅप <xliff:g id="APPLICATION">%1$s</xliff:g> (प्रक्रिया <xliff:g id="PROCESS">%2$s</xliff:g>) ने तिच्या स्वयं-लागू केलेल्या StrictMode धोरणाचे उल्लंघन केले आहे."</string>
@@ -1105,7 +1105,7 @@
     <string name="wifi_no_internet" msgid="8451173622563841546">"वाय-फायवरून इंटरनेटवर अॅक्सेस नाही"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"पर्यायांसाठी टॅप करा"</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"<xliff:g id="NETWORK_TYPE">%1$s</xliff:g> वर स्विच केले"</string>
-    <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> कडे इंटरनेट अॅक्सेस नसताना डीव्हाइस <xliff:g id="NEW_NETWORK">%1$s</xliff:g> वापरते. शुल्क लागू शकेल."</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"<xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> कडे इंटरनेट अॅक्सेस नसताना डिव्हाइस <xliff:g id="NEW_NETWORK">%1$s</xliff:g> वापरते. शुल्क लागू शकेल."</string>
     <string name="network_switch_metered_toast" msgid="5779283181685974304">"<xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g> वरून <xliff:g id="NEW_NETWORK">%2$s</xliff:g> वर स्विच केले"</string>
   <string-array name="network_switch_type_name">
     <item msgid="3979506840912951943">"मोबाइल डेटा"</item>
@@ -1154,7 +1154,7 @@
     <string name="sim_removed_message" msgid="2333164559970958645">"आपण एक वैध सिम कार्ड घालून प्रारंभ करेपर्यंत मोबाईल नेटवर्क अनुपलब्ध असेल."</string>
     <string name="sim_done_button" msgid="827949989369963775">"पूर्ण झाले"</string>
     <string name="sim_added_title" msgid="3719670512889674693">"सिम कार्ड जोडले"</string>
-    <string name="sim_added_message" msgid="6599945301141050216">"मोबाईल नेटवर्कवर अॅक्सेस करण्यासाठी तुमचे डीव्हाइस रीस्टार्ट करा."</string>
+    <string name="sim_added_message" msgid="6599945301141050216">"मोबाईल नेटवर्कवर अॅक्सेस करण्यासाठी तुमचे डिव्हाइस रीस्टार्ट करा."</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"रीस्टार्ट"</string>
     <string name="carrier_app_dialog_message" msgid="7066156088266319533">"आपल्या नवीन सिमने योग्यरित्या कार्य करण्यासाठी, आपल्याला अॅप इंस्टॉल करण्याची आणि तो आपल्या वाहकामधून उघडण्याची आवश्यकता असेल."</string>
     <string name="carrier_app_dialog_button" msgid="7900235513678617329">"अ‍ॅप मिळवा"</string>
@@ -1170,7 +1170,7 @@
     <string name="no_permissions" msgid="7283357728219338112">"परवानग्या आवश्यक नाहीत"</string>
     <string name="perm_costs_money" msgid="4902470324142151116">"यासाठी आपले पैसे खर्च होऊ शकतात"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"ठीक"</string>
-    <string name="usb_charging_notification_title" msgid="6895185153353640787">"USB हे डीव्हाइस चार्ज करत आहे"</string>
+    <string name="usb_charging_notification_title" msgid="6895185153353640787">"USB हे डिव्हाइस चार्ज करत आहे"</string>
     <string name="usb_supplying_notification_title" msgid="5310642257296510271">"USB संलग्न केलेल्या डिव्हाइसला पॉवरचा पुरवठा करीत आहे"</string>
     <string name="usb_mtp_notification_title" msgid="8396264943589760855">"स्थानांतरणासाठी USB"</string>
     <string name="usb_ptp_notification_title" msgid="1347328437083192112">"फोटो स्थानांतरणासाठी USB"</string>
@@ -1208,8 +1208,8 @@
     <string name="ext_media_unmountable_notification_message" msgid="2343202057122495773">"<xliff:g id="NAME">%s</xliff:g> दूषित आहे. निराकरण करण्यासाठी टॅप करा."</string>
     <string name="ext_media_unmountable_notification_message" product="tv" msgid="3941179940297874950">"<xliff:g id="NAME">%s</xliff:g> दूषित आहे. निश्चित करण्यासाठी निवडा."</string>
     <string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"<xliff:g id="NAME">%s</xliff:g> असमर्थित"</string>
-    <string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"हे डीव्हाइस <xliff:g id="NAME">%s</xliff:g> ला सपोर्ट करत नाही. सपोर्ट असलेल्या फॉरमॅटमध्ये सेट करण्यासाठी टॅप करा."</string>
-    <string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"हे डीव्हाइस <xliff:g id="NAME">%s</xliff:g> ला सपोर्ट करत नाही. सपोर्ट असलेल्या फॉरमॅटमध्ये सेट करण्यासाठी निवडा."</string>
+    <string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"हे डिव्हाइस <xliff:g id="NAME">%s</xliff:g> ला सपोर्ट करत नाही. सपोर्ट असलेल्या फॉरमॅटमध्ये सेट करण्यासाठी टॅप करा."</string>
+    <string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"हे डिव्हाइस <xliff:g id="NAME">%s</xliff:g> ला सपोर्ट करत नाही. सपोर्ट असलेल्या फॉरमॅटमध्ये सेट करण्यासाठी निवडा."</string>
     <string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g> अनपेक्षितरित्या काढले"</string>
     <string name="ext_media_badremoval_notification_message" msgid="380176703346946313">"डेटा गमावणे टाळण्‍यासाठी काढण्‍यापूर्वी <xliff:g id="NAME">%s</xliff:g> अनमाउंट करा"</string>
     <string name="ext_media_nomedia_notification_title" msgid="1704840188641749091">"<xliff:g id="NAME">%s</xliff:g> काढले"</string>
@@ -1220,7 +1220,7 @@
     <string name="ext_media_unmount_action" msgid="1121883233103278199">"बाहेर काढा"</string>
     <string name="ext_media_browse_action" msgid="8322172381028546087">"एक्सप्लोर करा"</string>
     <string name="ext_media_missing_title" msgid="620980315821543904">"<xliff:g id="NAME">%s</xliff:g> गहाळ आहे"</string>
-    <string name="ext_media_missing_message" msgid="5761133583368750174">"हे डीव्हाइस पुन्हा घाला"</string>
+    <string name="ext_media_missing_message" msgid="5761133583368750174">"हे डिव्हाइस पुन्हा घाला"</string>
     <string name="ext_media_move_specific_title" msgid="1471100343872375842">"<xliff:g id="NAME">%s</xliff:g> हलवित आहे"</string>
     <string name="ext_media_move_title" msgid="1022809140035962662">"डेटा हलवित आहे"</string>
     <string name="ext_media_move_success_title" msgid="8575300932957954671">"हलविणे पूर्ण"</string>
@@ -1615,7 +1615,7 @@
     <string name="package_installed_device_owner" msgid="6875717669960212648">"आपल्या प्रशासकाने इंस्टॉल केले"</string>
     <string name="package_updated_device_owner" msgid="1847154566357862089">"आपल्या प्रशासकाने अपडेट केले"</string>
     <string name="package_deleted_device_owner" msgid="2307122077550236438">"आपल्या प्रशासकाने हटवले"</string>
-    <string name="battery_saver_description" msgid="1960431123816253034">"बॅटरी लाइफ सुधारित करण्‍यासाठी, बॅटरी सेव्हर तुमच्या डीव्हाइस ची कामगिरी कमी करतो आणि कंपन, स्थान सेवा आणि बराच पार्श्वभूमी डेटा मर्यादित करतो. सिंकवर अवलंबून असणारे ईमेल, मेसेजिंग आणि इतर अ‍ॅप्स तुम्ही उघडल्याशिवाय अपडेट होऊ शकत नाहीत.\n\nतुमचे डीव्हाइस चार्ज होत असते तेव्हा बॅटरी सेव्हर आपोआप बंद होतो."</string>
+    <string name="battery_saver_description" msgid="1960431123816253034">"बॅटरी लाइफ सुधारित करण्‍यासाठी, बॅटरी सेव्हर तुमच्या डिव्हाइस ची कामगिरी कमी करतो आणि कंपन, स्थान सेवा आणि बराच पार्श्वभूमी डेटा मर्यादित करतो. सिंकवर अवलंबून असणारे ईमेल, मेसेजिंग आणि इतर अ‍ॅप्स तुम्ही उघडल्याशिवाय अपडेट होऊ शकत नाहीत.\n\nतुमचे डिव्हाइस चार्ज होत असते तेव्हा बॅटरी सेव्हर आपोआप बंद होतो."</string>
     <string name="data_saver_description" msgid="6015391409098303235">"डेटा वापर कमी करण्यात मदत करण्यासाठी, डेटा सर्व्हर काही अॅप्सना पार्श्वभूमीमध्ये डेटा पाठविण्यास किंवा प्राप्त करण्यास प्रतिबंधित करतो. आपण सध्या वापरत असलेला अॅप डेटामध्ये प्रवेश करू शकतो परंतु तसे तो खूप कमी वेळा करू शकतो. याचा अर्थ, उदाहरणार्थ, आपण इमेज टॅप करेपर्यंत त्या प्रदर्शित करणार नाहीत असा असू शकतो."</string>
     <string name="data_saver_enable_title" msgid="4674073932722787417">"डेटा बचतकर्ता चालू करायचा?"</string>
     <string name="data_saver_enable_button" msgid="7147735965247211818">"चालू करा"</string>
@@ -1716,7 +1716,7 @@
     <string name="app_info" msgid="6856026610594615344">"अॅप माहिती"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="demo_starting_message" msgid="5268556852031489931">"डेमो प्रारंभ करत आहे..."</string>
-    <string name="demo_restarting_message" msgid="952118052531642451">"डीव्हाइस रीसेट करत आहे..."</string>
+    <string name="demo_restarting_message" msgid="952118052531642451">"डिव्हाइस रीसेट करत आहे..."</string>
     <string name="suspended_widget_accessibility" msgid="6712143096475264190">"<xliff:g id="LABEL">%1$s</xliff:g> अक्षम केले"</string>
     <string name="conference_call" msgid="3751093130790472426">"परिषद कॉल"</string>
     <string name="tooltip_popup_title" msgid="5253721848739260181">"टूलटिप"</string>
@@ -1728,7 +1728,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"बातम्‍या आणि मासिके"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"नकाशे आणि नेव्हिगेशन"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"उत्पादनक्षमता"</string>
-    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"डीव्हाइस स्टोरेज"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"डिव्हाइस स्टोरेज"</string>
     <string name="adb_debugging_notification_channel_tv" msgid="5537766997350092316">"USB डीबगिंग"</string>
     <string name="time_picker_hour_label" msgid="2979075098868106450">"तास"</string>
     <string name="time_picker_minute_label" msgid="5168864173796598399">"मिनिट"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index c2b7a21..387c97a 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -343,7 +343,7 @@
     <string name="permdesc_writeSettings" msgid="7775723441558907181">"प्रणालीका सेटिङ डेटालाई परिवर्तन गर्नको लागि अनुप्रयोगलाई अनुमति दिन्छ। खराब अनुप्रयोगहरूले सायद तपाईँको प्रणालीको कन्फिगरेसनलाई क्षति पुर्‍याउन सक्छन्।"</string>
     <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"स्टार्टअपमा चलाउनुहोस्"</string>
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"आनुप्रयोगलाई प्रणाली बुट प्रक्रिया पूर्ण हुने बितिकै आफैलाई सुरु गर्ने अनुमति दिन्छ। यसले ट्याब्लेट सुरु गर्नमा ढिला गर्न सक्दछ र अनुप्रयोगलाई समग्रमा ट्याब्लेट सधैँ चालु गरेर ढिला बनाउँदछ।"</string>
-    <string name="permdesc_receiveBootCompleted" product="tv" msgid="4525890122209673621">"अनुप्रयोगलाई अनुमति दिन्छ प्रणालीले बुटिङ सकेपछि आफै सुरूवात हुन। यसले TV सुरू गर्न लामो समय लिन सक्छ र अनुप्रयोगहरूलाई अनुमति दिन सक्छ सँधै सञ्चालन भई समग्र रूपमा ट्याब्लेटलाई ढिलो गराएर।"</string>
+    <string name="permdesc_receiveBootCompleted" product="tv" msgid="4525890122209673621">"अनुप्रयोगलाई अनुमति दिन्छ प्रणालीले बुटिङ सकेपछि आफै सुरुवात हुन। यसले TV सुरु गर्न लामो समय लिन सक्छ र अनुप्रयोगहरूलाई अनुमति दिन सक्छ सँधै सञ्चालन भई समग्र रूपमा ट्याब्लेटलाई ढिलो गराएर।"</string>
     <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"अनुप्रयोगलाई प्रणाली बुट गरी सकेपछि जति सक्दो चाँडो आफैंमा सुरु गर्न अनुमति दिन्छ। यसले फोन सुरु गर्नमा ढिला गर्न सक्दछ र अनप्रयोगलाई समग्रमा फोन सधैँ चालु गरेर ढिला बनाउँदछ।"</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"स्टिकि प्रसारण पठाउनुहोस्"</string>
     <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"औपचारिक प्रसारणलाई पठाउनको लागि एउटा अनुप्रयोगलाई अनुमति दिन्छ, जुन प्रसारण समाप्त भएपछि बाँकी रहन्छ। अत्यधिक प्रयोगले धेरै मेमोरी प्रयोग गरेको कारणले ट्याब्लेटलाई ढिलो र अस्थिर बनाउन सक्छ।"</string>
@@ -1161,7 +1161,7 @@
     <string name="sim_done_button" msgid="827949989369963775">"भयो"</string>
     <string name="sim_added_title" msgid="3719670512889674693">"SIM कार्ड थप गरियो"</string>
     <string name="sim_added_message" msgid="6599945301141050216">"मोबाइल नेटवर्क पहुँच गर्न तपाईँको उपकरण पुनःस्टार्ट गर्नुहोस्।"</string>
-    <string name="sim_restart_button" msgid="4722407842815232347">"पुनः सुरू गर्नुहोस्"</string>
+    <string name="sim_restart_button" msgid="4722407842815232347">"पुनः सुरु गर्नुहोस्"</string>
     <string name="carrier_app_dialog_message" msgid="7066156088266319533">"तपाईंको नयाँ SIM ले राम्रोसँग काम गर्न, तपाईंले आफ्नो वाहक मार्फत अनुप्रयोग स्थापना र खोल्न आवश्यक हुनेछ।"</string>
     <string name="carrier_app_dialog_button" msgid="7900235513678617329">"अनुप्रयोग प्राप्त गर्नुहोस्"</string>
     <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"अहिले होइन"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 74315c0..09cf805 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -36,7 +36,7 @@
     <string name="serviceDisabled" msgid="1937553226592516411">"ਸੇਵਾ ਅਸਮਰੱਥ ਬਣਾਈ ਗਈ ਹੈ।"</string>
     <string name="serviceRegistered" msgid="6275019082598102493">"ਰਜਿਸਟਰੇਸ਼ਨ ਸਫਲ ਸੀ।"</string>
     <string name="serviceErased" msgid="1288584695297200972">"ਮਿਟਾਉਣਾ ਸਫ਼ਲ ਰਿਹਾ ਸੀ।"</string>
-    <string name="passwordIncorrect" msgid="7612208839450128715">"ਗ਼ਲਤ ਪਾਸਵਰਡ।"</string>
+    <string name="passwordIncorrect" msgid="7612208839450128715">"ਗਲਤ ਪਾਸਵਰਡ।"</string>
     <string name="mmiComplete" msgid="8232527495411698359">"MMI ਪੂਰਾ।"</string>
     <string name="badPin" msgid="9015277645546710014">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਟਾਈਪ ਕੀਤਾ ਪੁਰਾਣਾ ਪਿੰਨ ਠੀਕ ਨਹੀਂ ਹੈ।"</string>
     <string name="badPuk" msgid="5487257647081132201">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਟਾਈਪ ਕੀਤਾ PUK ਠੀਕ ਨਹੀਂ ਹੈ।"</string>
@@ -54,8 +54,8 @@
     <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"ਇਨਕਮਿੰਗ ਕਾਲਰ ਆਈ.ਡੀ."</string>
     <string name="ClirMmi" msgid="7784673673446833091">"ਆਊਟਗੋਇੰਗ ਕਾਲਰ ਆਈ.ਡੀ."</string>
-    <string name="ColpMmi" msgid="3065121483740183974">"ਕਨੈਕਟ ਕੀਤੀ ਲਾਈਨ ID"</string>
-    <string name="ColrMmi" msgid="4996540314421889589">"ਕਨੈਕਟ ਕੀਤੀ ਲਾਈਨ ID ਪ੍ਰਤਿਬੰਧ"</string>
+    <string name="ColpMmi" msgid="3065121483740183974">"ਕਨੈਕਟ ਕੀਤੀ ਲਾਈਨ ਆਈ.ਡੀ."</string>
+    <string name="ColrMmi" msgid="4996540314421889589">"ਕਨੈਕਟ ਕੀਤੀ ਲਾਈਨ ਆਈ.ਡੀ. ਪ੍ਰਤਿਬੰਧ"</string>
     <string name="CfMmi" msgid="5123218989141573515">"ਕਾਲ ਫਾਰਵਰਡਿੰਗ"</string>
     <string name="CwMmi" msgid="9129678056795016867">"ਕਾਲ ਦੀ ਉਡੀਕ"</string>
     <string name="BaMmi" msgid="455193067926770581">"ਕਾਲ ਬੈਰਿੰਗ"</string>
@@ -146,7 +146,7 @@
     <string name="httpErrorConnect" msgid="8714273236364640549">"ਸਰਵਰ ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਕਰ ਸਕਿਆ।"</string>
     <string name="httpErrorIO" msgid="2340558197489302188">"ਸਰਵਰ ਨਾਲ ਸੰਚਾਰ ਨਹੀਂ ਕਰ ਸਕਿਆ। ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="httpErrorTimeout" msgid="4743403703762883954">"ਸਰਵਰ ਨਾਲ ਕਨੈਕਸ਼ਨ ਦਾ ਸਮਾਂ ਸਮਾਪਤ ਹੋਇਆ।"</string>
-    <string name="httpErrorRedirectLoop" msgid="8679596090392779516">"ਸਫ਼ੇ ਵਿੱਚ ਬਹੁਤ ਜ਼ਿਆਦਾ ਰੀਡਾਇਰੈਕਟ ਸ਼ਾਮਲ ਹਨ।"</string>
+    <string name="httpErrorRedirectLoop" msgid="8679596090392779516">"ਪੰਨੇ ਵਿੱਚ ਬਹੁਤ ਜ਼ਿਆਦਾ ਰੀਡਾਇਰੈਕਟ ਸ਼ਾਮਲ ਹਨ।"</string>
     <string name="httpErrorUnsupportedScheme" msgid="5015730812906192208">"ਪ੍ਰੋਟੋਕੋਲ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ।"</string>
     <string name="httpErrorFailedSslHandshake" msgid="96549606000658641">"ਇੱਕ ਸੁਰੱਖਿਅਤ ਕਨੈਕਸ਼ਨ ਸਥਾਪਿਤ ਨਹੀਂ ਕਰ ਸਕਿਆ।"</string>
     <string name="httpErrorBadUrl" msgid="3636929722728881972">"ਪੰਨਾ ਨਹੀਂ ਖੋਲ੍ਹ ਸਕਿਆ ਕਿਉਂਕਿ URL ਅਵੈਧ ਹੈ।"</string>
@@ -158,9 +158,9 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"ਸਿੰਕ ਕਰੋ"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"ਬਹੁਤ ਜ਼ਿਆਦਾ <xliff:g id="CONTENT_TYPE">%s</xliff:g> ਮਿਟਾਏ।"</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"ਟੈਬਲੈੱਟ ਸਟੋਰੇਜ ਪੂਰੀ ਭਰੀ ਹੈ। ਜਗ੍ਹਾ ਖਾਲੀ ਕਰਨ ਲਈ ਕੁਝ ਫ਼ਾਈਲਾਂ ਮਿਟਾਓ।"</string>
-    <string name="low_memory" product="watch" msgid="4415914910770005166">"ਘੜੀ ਸਟੋਰੇਜ ਪੂਰੀ ਭਰੀ ਹੈ। ਸਪੇਸ ਖਾਲੀ ਕਰਨ ਲਈ ਕੁਝ ਫਾਈਲਾਂ ਮਿਟਾਓ।"</string>
-    <string name="low_memory" product="tv" msgid="516619861191025923">"TV ਸਟੋਰੇਜ ਪੂਰੀ ਭਰੀ ਹੈ। ਸਪੇਸ ਖਾਲੀ ਕਰਨ ਲਈ ਕੁਝ ਫਾਈਲਾਂ ਮਿਟਾਓ।"</string>
-    <string name="low_memory" product="default" msgid="3475999286680000541">"ਫੋਨ ਸਟੋਰੇਜ ਪੂਰੀ ਭਰੀ ਹੈ। ਸਪੇਸ ਖਾਲੀ ਕਰਨ ਲਈ ਕੁਝ ਫਾਈਲਾਂ ਮਿਟਾਓ।"</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"ਘੜੀ ਸਟੋਰੇਜ ਪੂਰੀ ਭਰੀ ਹੈ। ਜਗ੍ਹਾ ਖਾਲੀ ਕਰਨ ਲਈ ਕੁਝ ਫ਼ਾਈਲਾਂ ਮਿਟਾਓ।"</string>
+    <string name="low_memory" product="tv" msgid="516619861191025923">"ਟੀਵੀ ਸਟੋਰੇਜ ਪੂਰੀ ਭਰੀ ਹੈ। ਜਗ੍ਹਾ ਖਾਲੀ ਕਰਨ ਲਈ ਕੁਝ ਫ਼ਾਈਲਾਂ ਮਿਟਾਓ।"</string>
+    <string name="low_memory" product="default" msgid="3475999286680000541">"ਫ਼ੋਨ ਸਟੋਰੇਜ ਪੂਰੀ ਭਰੀ ਹੈ। ਜਗ੍ਹਾ ਖਾਲੀ ਕਰਨ ਲਈ ਕੁਝ ਫ਼ਾਈਲਾਂ ਮਿਟਾਓ।"</string>
     <plurals name="ssl_ca_cert_warning" formatted="false" msgid="5106721205300213569">
       <item quantity="one">ਪ੍ਰਮਾਣ-ਪੱਤਰ ਅਥਾਰਿਟੀਆਂ ਸਥਾਪਤ ਕੀਤੀਆਂ ਗਈਆਂ</item>
       <item quantity="other">ਪ੍ਰਮਾਣ-ਪੱਤਰ ਅਥਾਰਿਟੀਆਂ ਸਥਾਪਤ ਕੀਤੀਆਂ ਗਈਆਂ</item>
@@ -171,15 +171,15 @@
     <string name="work_profile_deleted" msgid="5005572078641980632">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਮਿਟਾਈ ਗਈ"</string>
     <string name="work_profile_deleted_description" msgid="1100529432509639864">"ਗੁੰਮਸ਼ੁਦਾ ਪ੍ਰਸ਼ਾਸਕ ਐਪ ਦੇ ਕਾਰਨ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਮਿਟਾਇਆ ਗਿਆ"</string>
     <string name="work_profile_deleted_details" msgid="6307630639269092360">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਪ੍ਰਸ਼ਾਸਕ ਐਪ ਜਾਂ ਤਾਂ ਗੁੰਮਸ਼ੁਦਾ ਹੈ ਜਾਂ ਖਰਾਬ ਹੈ। ਨਤੀਜੇ ਵਜੋਂ, ਤੁਹਾਡੀ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਅਤੇ ਸਬੰਧਿਤ ਡਾਟਾ ਮਿਟਾਇਆ ਗਿਆ ਹੈ। ਸਹਾਇਤਾ ਲਈ ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string>
-    <string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"ਤੁਹਾਡੀ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹੁਣ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
+    <string name="work_profile_deleted_description_dpm_wipe" msgid="8823792115612348820">"ਤੁਹਾਡਾ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹੁਣ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
     <string name="network_logging_notification_title" msgid="6399790108123704477">"ਡੀਵਾਈਸ ਪ੍ਰਬੰਧਨ ਅਧੀਨ ਹੈ"</string>
     <string name="network_logging_notification_text" msgid="7930089249949354026">"ਤੁਹਾਡਾ ਸੰਗਠਨ ਇਸ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਦਾ ਹੈ ਅਤੇ ਨੈੱਟਵਰਕ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦਾ ਹੈ। ਵੇਰਵਿਆਂ ਲਈ ਟੈਪ ਕਰੋ।"</string>
     <string name="factory_reset_warning" msgid="5423253125642394387">"ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਮਿਟਾਇਆ ਜਾਏਗਾ"</string>
-    <string name="factory_reset_message" msgid="7972496262232832457">"ਪ੍ਰਸ਼ਾਸਕ ਐਪ ਵਰਤੀ ਨਹੀਂ ਜਾ ਸਕਦੀ। ਹੁਣ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦਾ ਡਾਟਾ ਮਿਟਾਇਆ ਜਾਵੇਗਾ।\n\nਜੇਕਰ ਤੁਹਾਡੇ ਕੋਲ ਕੋਈ ਸਵਾਲ ਹਨ, ਤਾਂ ਆਪਣੀ ਸੰਸਥਾ ਦੇ ਪ੍ਰਸ਼ਾਸਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string>
+    <string name="factory_reset_message" msgid="7972496262232832457">"ਪ੍ਰਸ਼ਾਸਕ ਐਪ ਵਰਤੀ ਨਹੀਂ ਜਾ ਸਕਦੀ। ਹੁਣ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦਾ ਡਾਟਾ ਮਿਟਾਇਆ ਜਾਵੇਗਾ।\n\nਜੇਕਰ ਤੁਹਾਡੇ ਕੋਲ ਕੋਈ ਸਵਾਲ ਹਨ, ਤਾਂ ਆਪਣੀ ਸੰਸਥਾ ਦੇ ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
     <string name="me" msgid="6545696007631404292">"ਮੈਂ"</string>
     <string name="power_dialog" product="tablet" msgid="8545351420865202853">"ਟੈਬਲੈੱਟ ਵਿਕਲਪ"</string>
     <string name="power_dialog" product="tv" msgid="6153888706430556356">"TV ਚੋਣਾਂ"</string>
-    <string name="power_dialog" product="default" msgid="1319919075463988638">"ਫੋਨ ਚੋਣਾਂ"</string>
+    <string name="power_dialog" product="default" msgid="1319919075463988638">"ਫ਼ੋਨ ਚੋਣਾਂ"</string>
     <string name="silent_mode" msgid="7167703389802618663">"ਸਾਈਲੈਂਟ ਮੋਡ"</string>
     <string name="turn_on_radio" msgid="3912793092339962371">"ਵਾਇਰਲੈਸ ਚਾਲੂ ਕਰੋ"</string>
     <string name="turn_off_radio" msgid="8198784949987062346">"ਵਾਇਰਲੈਸ ਬੰਦ ਕਰੋ"</string>
@@ -188,9 +188,9 @@
     <string name="silent_mode_silent" msgid="319298163018473078">"ਰਿੰਗਰ ਬੰਦ"</string>
     <string name="silent_mode_vibrate" msgid="7072043388581551395">"ਰਿੰਗਰ ਥਰਥਰਾਹਟ"</string>
     <string name="silent_mode_ring" msgid="8592241816194074353">"ਰਿੰਗਰ ਚਾਲੂ"</string>
-    <string name="reboot_to_update_title" msgid="6212636802536823850">"Android ਸਿਸਟਮ ਅਪਡੇਟ"</string>
-    <string name="reboot_to_update_prepare" msgid="6305853831955310890">"ਅਪਡੇਟ ਦੀ ਤਿਆਰੀ ਕਰ ਰਿਹਾ ਹੈ…"</string>
-    <string name="reboot_to_update_package" msgid="3871302324500927291">"ਅਪਡੇਟ ਪੈਕੇਜ ਦੀ ਕਾਰਵਾਈ ਕਰ ਰਿਹਾ ਹੈ..."</string>
+    <string name="reboot_to_update_title" msgid="6212636802536823850">"Android ਸਿਸਟਮ ਅੱਪਡੇਟ"</string>
+    <string name="reboot_to_update_prepare" msgid="6305853831955310890">"ਅੱਪਡੇਟ ਦੀ ਤਿਆਰੀ ਕਰ ਰਿਹਾ ਹੈ…"</string>
+    <string name="reboot_to_update_package" msgid="3871302324500927291">"ਅੱਪਡੇਟ ਪੈਕੇਜ ਦੀ ਕਾਰਵਾਈ ਕਰ ਰਿਹਾ ਹੈ..."</string>
     <string name="reboot_to_update_reboot" msgid="6428441000951565185">"ਰੀਸਟਾਰਟ ਹੋ ਰਿਹਾ ਹੈ…"</string>
     <string name="reboot_to_reset_title" msgid="4142355915340627490">"ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ"</string>
     <string name="reboot_to_reset_message" msgid="2432077491101416345">"ਰੀਸਟਾਰਟ ਹੋ ਰਿਹਾ ਹੈ…"</string>
@@ -198,7 +198,7 @@
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"ਤੁਹਾਡਾ ਟੈਬਲੈੱਟ ਬੰਦ ਕੀਤਾ ਜਾਵੇਗਾ।"</string>
     <string name="shutdown_confirm" product="tv" msgid="476672373995075359">"ਤੁਹਾਡਾ TV ਬੰਦ ਕੀਤਾ ਜਾਏਗਾ।"</string>
     <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"ਤੁਹਾਡੀ ਘੜੀ ਬੰਦ ਕੀਤੀ ਜਾਏਗੀ।"</string>
-    <string name="shutdown_confirm" product="default" msgid="649792175242821353">"ਤੁਹਾਡਾ ਫੋਨ ਬੰਦ ਕੀਤਾ ਜਾਏਗਾ।"</string>
+    <string name="shutdown_confirm" product="default" msgid="649792175242821353">"ਤੁਹਾਡਾ ਫ਼ੋਨ ਬੰਦ ਕੀਤਾ ਜਾਏਗਾ।"</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"ਕੀ ਤੁਸੀਂ ਬੰਦ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"ਮੋਡ ਸੁਰੱਖਿਅਤ ਕਰਨ ਲਈ ਰੀਬੂਟ ਕਰੋ"</string>
     <string name="reboot_safemode_confirm" msgid="55293944502784668">"ਕੀ ਤੁਸੀਂ ਸੁਰੱਖਿਅਤ ਮੋਡ ਵਿੱਚ ਰੀਬੂਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? ਇਹ ਤੁਹਾਡੇ ਵੱਲੋਂ ਇੰਸਟੌਲ ਕੀਤੀਆਂ ਤੀਜੀ ਪਾਰਟੀ ਦੀਆਂ ਸਾਰੀਆਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾ ਦੇਵੇਗਾ। ਜਦੋਂ ਤੁਸੀਂ ਦੁਬਾਰਾ ਰੀਬੂਟ ਕਰੋਂਗੇ ਤਾਂ ਇਸਨੂੰ ਰੀਸਟੋਰ ਕੀਤਾ ਜਾਏਗਾ।"</string>
@@ -206,7 +206,7 @@
     <string name="no_recent_tasks" msgid="8794906658732193473">"ਕੋਈ ਹਾਲੀਆ ਐਪਸ ਨਹੀਂ।"</string>
     <string name="global_actions" product="tablet" msgid="408477140088053665">"ਟੈਬਲੈੱਟ ਵਿਕਲਪ"</string>
     <string name="global_actions" product="tv" msgid="7240386462508182976">"TV ਚੋਣਾਂ"</string>
-    <string name="global_actions" product="default" msgid="2406416831541615258">"ਫੋਨ ਚੋਣਾਂ"</string>
+    <string name="global_actions" product="default" msgid="2406416831541615258">"ਫ਼ੋਨ ਚੋਣਾਂ"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"ਸਕ੍ਰੀਨ ਲੌਕ"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"ਪਾਵਰ ਬੰਦ"</string>
     <string name="global_action_emergency" msgid="7112311161137421166">"ਸੰਕਟਕਾਲ"</string>
@@ -216,10 +216,10 @@
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"ਅੰਤਰਕਿਰਿਆਤਮਕ ਰਿਪੋਰਟ"</string>
     <string name="bugreport_option_interactive_summary" msgid="229299488536107968">"ਜ਼ਿਆਦਾਤਰ ਹਾਲਾਤਾਂ ਵਿੱਚ ਇਸ ਦੀ ਵਰਤੋਂ ਕਰੋ। ਇਹ ਤੁਹਾਨੂੰ ਰਿਪੋਰਟ ਦੀ ਪ੍ਰਗਤੀ ਨੂੰ ਟਰੈਕ ਕਰਨ, ਸਮੱਸਿਆ ਬਾਰੇ ਹੋਰ ਵੇਰਵੇ ਦਾਖਲ ਕਰਨ, ਅਤੇ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲੈਣ ਦਿੰਦਾ ਹੈ। ਇਹ ਉਹਨਾਂ ਘੱਟ-ਵਰਤੇ ਗਏ ਕੁਝ ਭਾਗਾਂ ਨੂੰ ਨਜ਼ਰ-ਅੰਦਾਜ਼ ਕਰ ਸਕਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਦੀ ਰਿਪੋਰਟ ਕਰਨ ਵਿੱਚ ਵੱਧ ਸਮਾਂ ਲੱਗ ਸਕਦਾ ਹੈ।"</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"ਪੂਰੀ ਰਿਪੋਰਟ"</string>
-    <string name="bugreport_option_full_summary" msgid="7210859858969115745">"ਜਦੋਂ ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਪ੍ਰਤਿਕਿਰਿਆ ਨਾ ਕਰ ਰਿਹਾ ਹੋਵੇ ਜਾਂ ਬਹੁਤ ਹੀ ਹੌਲੀ ਹੋਵੇ, ਜਾਂ ਜਦੋਂ ਤੁਹਾਨੂੰ ਸਾਰੇ ਰਿਪੋਰਟ ਭਾਗਾਂ ਦੀ ਲੋੜ ਹੋਵੇ ਤਾਂ ਇਸ ਚੋਣ ਦੀ ਵਰਤੋਂ ਘੱਟ-ਘੱਟ ਸਿਸਟਮ ਦਖ਼ਲ ਲਈ ਕਰੋ। ਤੁਹਾਨੂੰ ਹੋਰ ਵੇਰਵੇ ਦਾਖਲ ਕਰਨ ਜਾਂ ਵਾਧੂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਨਹੀਂ ਲੈਣ ਦਿੰਦਾ ਹੈ।"</string>
+    <string name="bugreport_option_full_summary" msgid="7210859858969115745">"ਜਦੋਂ ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਪ੍ਰਤਿਕਿਰਿਆ ਨਾ ਕਰ ਰਿਹਾ ਹੋਵੇ ਜਾਂ ਬਹੁਤ ਹੀ ਹੌਲੀ ਹੋਵੇ, ਜਾਂ ਜਦੋਂ ਤੁਹਾਨੂੰ ਸਾਰੇ ਰਿਪੋਰਟ ਭਾਗਾਂ ਦੀ ਲੋੜ ਹੋਵੇ ਤਾਂ ਇਸ ਚੋਣ ਦੀ ਵਰਤੋਂ ਘੱਟ-ਘੱਟ ਸਿਸਟਮ ਦਖਲ ਲਈ ਕਰੋ। ਤੁਹਾਨੂੰ ਹੋਰ ਵੇਰਵੇ ਦਾਖਲ ਕਰਨ ਜਾਂ ਵਾਧੂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਨਹੀਂ ਲੈਣ ਦਿੰਦਾ ਹੈ।"</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
-      <item quantity="one">ਬੱਗ ਰਿਪੋਰਟ ਲਈ <xliff:g id="NUMBER_1">%d</xliff:g> ਸਕਿੰਟ ਵਿੱਚ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲਿਆ ਜਾ ਰਿਹਾ ਹੈ।</item>
-      <item quantity="other">ਬੱਗ ਰਿਪੋਰਟ ਲਈ <xliff:g id="NUMBER_1">%d</xliff:g> ਸਕਿੰਟ ਵਿੱਚ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲਿਆ ਜਾ ਰਿਹਾ ਹੈ।</item>
+      <item quantity="one">ਬੱਗ ਰਿਪੋਰਟ ਲਈ <xliff:g id="NUMBER_1">%d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲਿਆ ਜਾ ਰਿਹਾ ਹੈ।</item>
+      <item quantity="other">ਬੱਗ ਰਿਪੋਰਟ ਲਈ <xliff:g id="NUMBER_1">%d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲਿਆ ਜਾ ਰਿਹਾ ਹੈ।</item>
     </plurals>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"ਸਾਈਲੈਂਟ ਮੋਡ"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"ਅਵਾਜ਼ ਬੰਦ ਹੈ"</string>
@@ -260,18 +260,18 @@
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"ਸੰਪਰਕ"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"ਆਪਣੇ ਸੰਪਰਕਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"ਟਿਕਾਣਾ"</string>
-    <string name="permgroupdesc_location" msgid="1346617465127855033">"ਇਸ ਡੀਵਾਈਸ ਦੇ ਨਿਰਧਾਰਿਤ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string>
+    <string name="permgroupdesc_location" msgid="1346617465127855033">"ਇਸ ਡੀਵਾਈਸ ਦੇ ਨਿਰਧਾਰਤ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚੋ"</string>
     <string name="permgrouplab_calendar" msgid="5863508437783683902">"ਕੈਲੰਡਰ"</string>
     <string name="permgroupdesc_calendar" msgid="3889615280211184106">"ਤੁਹਾਡੇ ਕੈਲੰਡਰ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string>
     <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="4656988620100940350">"SMS ਸੁਨੇਹੇ ਭੇਜੋ ਅਤੇ ਦੇਖੋ"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"ਸਟੋਰੇਜ"</string>
-    <string name="permgroupdesc_storage" msgid="637758554581589203">"ਆਪਣੇ ਡੀਵਾਈਸ \'ਤੇ ਫ਼ੋਟੋਆਂ, ਮੀਡੀਆ ਅਤੇ ਫ਼ਾਈਲਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string>
+    <string name="permgroupdesc_storage" msgid="637758554581589203">"ਆਪਣੇ ਡੀਵਾਈਸ \'ਤੇ ਫ਼ੋਟੋਆਂ, ਮੀਡੀਆ ਅਤੇ ਫ਼ਾਈਲਾਂ ਤੱਕ ਪਹੁੰਚ ਕਰਨਾ"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"ਮਾਈਕ੍ਰੋਫੋਨ"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">" ਆਡੀਓ  ਰਿਕਾਰਡ ਕਰਨ"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"ਕੈਮਰਾ"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"ਤਸਵੀਰਾਂ ਲੈਣ ਅਤੇ ਵੀਡੀਓ ਰਿਕਾਰਡ ਕਰਨ"</string>
-    <string name="permgrouplab_phone" msgid="5229115638567440675">"ਫੋਨ"</string>
+    <string name="permgrouplab_phone" msgid="5229115638567440675">"ਫ਼ੋਨ ਕਰੋ"</string>
     <string name="permgroupdesc_phone" msgid="6234224354060641055">"ਫ਼ੋਨ ਕਾਲਾਂ ਕਰਨ ਅਤੇ ਉਹਨਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰਨ"</string>
     <string name="permgrouplab_sensors" msgid="416037179223226722">"ਸਰੀਰ ਸੰਵੇਦਕ"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"ਆਪਣੇ ਸਰੀਰ ਦੇ ਅਹਿਮ ਚਿੰਨ੍ਹਾਂ ਬਾਰੇ ਸੰਵੇਦਕ ਡਾਟਾ ਤੱਕ ਪਹੁੰਚ ਕਰਨ"</string>
@@ -282,20 +282,20 @@
     <string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਟਾਈਪ ਕੀਤੀ ਲਿਖਤ ਦਾ ਨਿਰੀਖਣ ਕਰਨਾ"</string>
     <string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"ਇਸ ਵਿੱਚ ਨਿੱਜੀ  ਡਾਟਾ  ਸ਼ਾਮਲ ਹੈ ਜਿਵੇਂ ਕ੍ਰੈਡਿਟ ਕਾਰਡ ਨੰਬਰ ਅਤੇ ਪਾਸਵਰਡ।"</string>
     <string name="capability_title_canControlMagnification" msgid="3593493281059424855">"ਡਿਸਪਲੇ ਵੱਡਦਰਸ਼ੀਕਰਨ ਨੂੰ ਕੰਟਰੋਲ ਕਰਨਾ"</string>
-    <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ਡਿਸਪਲੇ ਦੇ ਜ਼ੂਮ ਪੱਧਰ ਅਤੇ ਸਥਿਤੀ ਨੂੰ ਨਿਯੰਤ੍ਰਿਤ ਕਰੋ।"</string>
+    <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"ਡਿਸਪਲੇ ਦੇ ਜ਼ੂਮ ਪੱਧਰ ਅਤੇ ਸਥਿਤੀ ਨੂੰ ਕੰਟਰੋਲ ਕਰੋ।"</string>
     <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"ਸੰਕੇਤ ਕਰਦੀ ਹੈ"</string>
-    <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ਟੈਪ ਕਰ ਸਕਦੀ ਹੈ, ਸਵਾਈਪ ਕਰ ਸਕਦੀ ਹੈ, ਪਿੰਚ ਕਰ ਸਕਦੀ ਹੈ, ਅਤੇ ਹੋਰ ਸੰਕੇਤ ਕਰ ਸਕਦੀ ਹੈ।"</string>
+    <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"ਟੈਪ ਕਰ ਸਕਦੀ ਹੈ, ਸਵਾਈਪ ਕਰ ਸਕਦੀ ਹੈ, ਚੂੰਢੀ ਭਰ ਸਕਦੀ ਹੈ, ਅਤੇ ਹੋਰ ਸੰਕੇਤ ਕਰ ਸਕਦੀ ਹੈ।"</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੰਕੇਤ"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="7102111919385702482">"ਡੀਵਾਈਸਾਂ ਦੇ ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ \'ਤੇ ਕੀਤੇ ਗਏ ਸੰਕੇਤਾਂ ਨੂੰ ਕੈਪਚਰ ਕਰ ਸਕਦੀ ਹੈ।"</string>
-    <string name="permlab_statusBar" msgid="7417192629601890791">"ਸਥਿਤੀ ਬਾਰ ਅਸਮਰੱਥ ਬਣਾਓ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰੋ"</string>
-    <string name="permdesc_statusBar" msgid="8434669549504290975">"ਐਪ ਨੂੰ ਸਥਿਤੀ ਬਾਰ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਉਣ ਜਾਂ ਸਿਸਟਮ ਆਈਕਨਾਂ ਨੂੰ ਜੋੜਨ ਅਤੇ ਹਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+    <string name="permlab_statusBar" msgid="7417192629601890791">"ਸਥਿਤੀ ਪੱਟੀ ਬੰਦ ਕਰੋ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰੋ"</string>
+    <string name="permdesc_statusBar" msgid="8434669549504290975">"ਐਪ ਨੂੰ ਸਥਿਤੀ ਪੱਟੀ ਨੂੰ ਚਾਲੂ ਕਰਨ ਜਾਂ ਸਿਸਟਮ ਪ੍ਰਤੀਕਾਂ ਨੂੰ ਜੋੜਨ ਅਤੇ ਹਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ਸਥਿਤੀ ਪੱਟੀ ਬਣਨ ਦਿਓ"</string>
-    <string name="permdesc_statusBarService" msgid="716113660795976060">"ਐਪ ਨੂੰ ਸਥਿਤੀ ਬਾਰ ਹੋਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
-    <string name="permlab_expandStatusBar" msgid="1148198785937489264">"ਸਥਿਤੀ ਪੱਟੀ ਦਾ ਵਿਸਤਾਰ/ਸੰਖਿਪਤ ਕਰੋ"</string>
+    <string name="permdesc_statusBarService" msgid="716113660795976060">"ਐਪ ਨੂੰ ਸਥਿਤੀ ਪੱਟੀ ਹੋਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+    <string name="permlab_expandStatusBar" msgid="1148198785937489264">"ਸਥਿਤੀ ਪੱਟੀ ਦਾ ਵਿਸਤਾਰ/ਨਸ਼ਟ ਕਰੋ"</string>
     <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"ਐਪ ਨੂੰ ਸਥਿਤੀ ਪੱਟੀ ਦਾ ਵਿਸਤਾਰ ਕਰਨ ਜਾਂ ਨਸ਼ਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
-    <string name="permlab_install_shortcut" msgid="4279070216371564234">"ਸ਼ਾਰਟਕੱਟ ਇੰਸਟੌਲ ਕਰੋ"</string>
-    <string name="permdesc_install_shortcut" msgid="8341295916286736996">"ਇੱਕ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਉਪਭੋਗਤਾ ਦੇ ਦਖ਼ਲ ਤੋਂ ਬਿਨਾਂ ਹੋਮਸਕ੍ਰੀਨ ਸ਼ਾਰਟਕੱਟ ਜੋੜਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
-    <string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"ਸ਼ਾਰਟਕੱਟ ਅਣਇੰਸਟੌਲ ਕਰੋ"</string>
+    <string name="permlab_install_shortcut" msgid="4279070216371564234">"ਸ਼ਾਰਟਕੱਟ ਸਥਾਪਤ ਕਰੋ"</string>
+    <string name="permdesc_install_shortcut" msgid="8341295916286736996">"ਇੱਕ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਵਰਤੋਂਕਾਰ ਦੇ ਦਖ਼ਲ ਤੋਂ ਬਿਨਾਂ ਹੋਮਸਕ੍ਰੀਨ ਸ਼ਾਰਟਕੱਟ ਸ਼ਾਮਲ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+    <string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"ਸ਼ਾਰਟਕੱਟ ਅਣਸਥਾਪਤ ਕਰੋ"</string>
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਵਰਤੋਂਕਾਰ ਦਖ਼ਲ ਤੋਂ ਬਿਨਾਂ ਹੋਮਸਕ੍ਰੀਨ ਸ਼ਾਰਟਕੱਟ ਹਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"ਆਊਟਗੋਇੰਗ ਕਾਲਾਂ ਰੀਰੂਟ ਕਰੋ"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"ਐਪ ਨੂੰ ਇੱਕ ਵੱਖ ਨੰਬਰ ਨਾਲ ਕਾਲ ਰੀਡਾਇਰੈਕਟ ਕਰਨ ਜਾਂ ਕਾਲ ਨੂੰ ਪੂਰਾ ਰੋਕਣ ਦੀ ਚੋਣ ਨਾਲ ਇੱਕ ਆਊਟਗੋਇੰਗ ਕਾਲ ਦੇ ਦੌਰਾਨ ਡਾਇਲ ਕੀਤਾ ਜਾ ਰਿਹਾ ਨੰਬਰ ਦੇਖਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
@@ -306,7 +306,7 @@
     <string name="permlab_receiveMms" msgid="1821317344668257098">"ਟੈਕਸਟ ਸੁਨੇਹੇ (MMS) ਪੜ੍ਹੋ"</string>
     <string name="permdesc_receiveMms" msgid="533019437263212260">"ਐਪ ਨੂੰ MMS ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਕਰਨ ਅਤੇ ਉਹਨਾਂ ਦੀ ਪ੍ਰਕਿਰਿਆ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸਦਾ ਮਤਲਬ ਹੈ ਕਿ ਐਪ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਤੇ ਭੇਜੇ ਗਏ ਸੁਨੇਹਿਆਂ ਨੂੰ ਤੁਹਾਨੂੰ ਦਿਖਾਏ ਬਿਨਾਂ ਨਿਰੀਖਣ ਕਰ ਸਕਦੀ ਹੈ ਜਾਂ ਮਿਟਾ ਸਕਦੀ ਹੈ।"</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"ਸੈਲ ਪ੍ਰਸਾਰਨ ਸੁਨੇਹੇ ਪੜ੍ਹੋ"</string>
-    <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ਐਪ ਨੂੰ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਵੱਲੋਂ ਪ੍ਰਾਪਤ ਕੀਤੇ ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਸੁਨੇਹੇ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਚਿਤਾਵਨੀਆਂ ਤੁਹਾਨੂੰ ਸੰਕਟਕਾਲੀਨ ਸਥਿਤੀਆਂ ਦੀ ਚਿਤਾਵਨੀ ਦੇਣ ਲਈ ਕੁਝ ਨਿਰਧਾਰਿਤ ਟਿਕਾਣਿਆਂ ਤੇ ਪ੍ਰਦਾਨ ਕੀਤੀਆਂ ਜਾਂਦੀਆਂ ਹਨ। ਖਰਾਬ ਐਪਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੇ ਪ੍ਰਦਰਸ਼ਨ ਜਾਂ ਓਪਰੇਸ਼ਨ ਵਿੱਚ ਵਿਘਨ ਪਾ ਸਕਦੀਆਂ ਹਨ ਜਦੋਂ ਇੱਕ ਸੰਕਟਕਾਲੀਨ ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਪ੍ਰਾਪਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।"</string>
+    <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"ਐਪ ਨੂੰ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਵੱਲੋਂ ਪ੍ਰਾਪਤ ਕੀਤੇ ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਸੁਨੇਹੇ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਚਿਤਾਵਨੀਆਂ ਤੁਹਾਨੂੰ ਸੰਕਟਕਾਲੀਨ ਸਥਿਤੀਆਂ ਦੀ ਚਿਤਾਵਨੀ ਦੇਣ ਲਈ ਕੁਝ ਨਿਰਧਾਰਤ ਟਿਕਾਣਿਆਂ ਤੇ ਪ੍ਰਦਾਨ ਕੀਤੀਆਂ ਜਾਂਦੀਆਂ ਹਨ। ਖਰਾਬ ਐਪਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੇ ਪ੍ਰਦਰਸ਼ਨ ਜਾਂ ਓਪਰੇਸ਼ਨ ਵਿੱਚ ਵਿਘਨ ਪਾ ਸਕਦੀਆਂ ਹਨ ਜਦੋਂ ਇੱਕ ਸੰਕਟਕਾਲੀਨ ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਪ੍ਰਾਪਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"ਸਬਸਕ੍ਰਾਈਬ ਕੀਤੇ ਫੀਡਸ ਪੜ੍ਹੋ"</string>
     <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"ਐਪ ਨੂੰ ਵਰਤਮਾਨ ਵਿੱਚ ਸਿੰਕ ਕੀਤੇ ਫੀਡਸ ਬਾਰੇ ਵੇਰਵੇ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_sendSms" msgid="7544599214260982981">"SMS ਸੁਨੇਹੇ ਭੇਜੋ ਅਤੇ ਦੇਖੋ"</string>
@@ -316,11 +316,11 @@
     <string name="permdesc_readSms" product="tv" msgid="5796670395641116592">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਟੀਵੀ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਸਾਰੇ SMS (ਲਿਖਤ) ਸੁਨੇਹਿਆਂ ਨੂੰ ਪੜ੍ਹ ਸਕਦੀ ਹੈ।"</string>
     <string name="permdesc_readSms" product="default" msgid="6826832415656437652">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਸਾਰੇ SMS (ਲਿਖਤ) ਸੁਨੇਹਿਆਂ ਨੂੰ ਪੜ੍ਹ ਸਕਦੀ ਹੈ।"</string>
     <string name="permlab_receiveWapPush" msgid="5991398711936590410">"ਟੈਕਸਟ ਸੁਨੇਹੇ (WAP) ਪ੍ਰਾਪਤ ਕਰੋ"</string>
-    <string name="permdesc_receiveWapPush" msgid="748232190220583385">"ਐਪ ਨੂੰ WAP ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਕਰਨ ਅਤੇ ਉਹਨਾਂ ਦੀ ਪ੍ਰਕਿਰਿਆ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸ ਅਨੁਮਤੀ ਵਿੱਚ ਸ਼ਾਮਲ ਹੈ ਐਪ ਦੀ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਤੇ ਭੇਜੇ ਗਏ ਸੁਨੇਹਿਆਂ ਨੂੰ ਤੁਹਾਨੂੰ ਦਿਖਾਏ ਬਿਨਾਂ ਨਿਰੀਖਣ ਕਰਨ ਅਤੇ ਮਿਟਾਉਣ ਦੀ ਸਮਰੱਥਾ।"</string>
+    <string name="permdesc_receiveWapPush" msgid="748232190220583385">"ਐਪ ਨੂੰ WAP ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਕਰਨ ਅਤੇ ਉਹਨਾਂ ਦੀ ਪ੍ਰਕਿਰਿਆ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸ ਇਜਾਜ਼ਤ ਵਿੱਚ ਸ਼ਾਮਲ ਹੈ ਐਪ ਦੀ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਤੇ ਭੇਜੇ ਗਏ ਸੁਨੇਹਿਆਂ ਨੂੰ ਤੁਹਾਨੂੰ ਦਿਖਾਏ ਬਿਨਾਂ ਨਿਰੀਖਣ ਕਰਨ ਅਤੇ ਮਿਟਾਉਣ ਦੀ ਸਮਰੱਥਾ।"</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"ਚੱਲ ਰਹੇ ਐਪਸ ਮੁੜ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"ਐਪ ਨੂੰ ਵਰਤਮਾਨ ਵਿੱਚ ਅਤੇ ਹੁਣੇ ਜਿਹੇ ਚੱਲ ਰਹੇ ਕੰਮਾਂ ਬਾਰੇ ਵਿਸਤ੍ਰਿਤ ਜਾਣਕਾਰੀ ਮੁੜ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਐਪ ਨੂੰ ਇਸ ਬਾਰੇ ਜਾਣਕਾਰੀ ਖੋਜਣ ਦੀ ਆਗਿਆ ਦੇ ਸਕਦਾ ਹੈ ਕਿ ਡੀਵਾਈਸ ਤੇ ਕਿਹੜੀਆਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਵਰਤੀਆਂ ਜਾਂਦੀਆਂ ਹਨ।"</string>
     <string name="permlab_manageProfileAndDeviceOwners" msgid="7918181259098220004">"ਪ੍ਰੋਫਾਈਲ ਅਤੇ ਡੀਵਾਈਸ ਮਾਲਕਾਂ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰੋ"</string>
-    <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"ਪ੍ਰੋਫਾਈਲ ਦੇ ਮਾਲਕ ਅਤੇ ਡੀਵਾਈਸ ਦੇ ਮਾਲਕ ਨੂੰ ਸੈੱਟ ਕਰਨ ਲਈ ਐਪਾਂ ਨੂੰ ਅਨੁਮਤੀ ਦਿੰਦਾ ਹੈ।"</string>
+    <string name="permdesc_manageProfileAndDeviceOwners" msgid="106894851498657169">"ਪ੍ਰੋਫਾਈਲ ਦੇ ਮਾਲਕ ਅਤੇ ਡੀਵਾਈਸ ਦੇ ਮਾਲਕ ਨੂੰ ਸੈੱਟ ਕਰਨ ਲਈ ਐਪਾਂ ਨੂੰ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_reorderTasks" msgid="2018575526934422779">"ਚੱਲ ਰਹੇ ਐਪਸ ਨੂੰ ਦੁਬਾਰਾ ਕ੍ਰਮ ਦਿਓ"</string>
     <string name="permdesc_reorderTasks" msgid="7734217754877439351">"ਐਪ ਨੂੰ ਕੰਮਾਂ ਨੂੰ ਅਗਲੇ ਭਾਗ ਅਤੇ ਪਿਛੋਕੜ ਵਿੱਚ ਮੂਵ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਐਪ ਤੁਹਾਡੇ ਇਨਪੁਟ ਤੋਂ ਬਿਨਾਂ ਇਹ ਕਰ ਸਕਦਾ ਹੈ।"</string>
     <string name="permlab_enableCarMode" msgid="5684504058192921098">"ਕਾਰ ਮੋਡ ਚਾਲੂ ਕਰੋ"</string>
@@ -336,47 +336,47 @@
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"ਐਪ ਨੂੰ ਹਮੇਸ਼ਾਂ ਚਲਾਏ ਰੱਖੋ"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"ਐਪ ਨੂੰ ਮੈਮਰੀ ਵਿੱਚ ਖੁਦ ਦੇ ਭਾਗਾਂ ਨੂੰ ਸਥਾਈ ਬਣਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਟੈਬਲੈੱਟ ਨੂੰ ਹੌਲੀ ਕਰਦੇ ਹੋਏ ਹੋਰਾਂ ਐਪਾਂ ਲਈ ਉਪਲਬਧ ਮੈਮਰੀ ਨੂੰ ਸੀਮਿਤ ਕਰ ਸਕਦਾ ਹੈ।"</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"ਐਪ ਨੂੰ ਮੈਮਰੀ ਵਿੱਚ ਖੁਦ ਦੇ ਭਾਗਾਂ ਨੂੰ ਸਥਾਈ ਬਣਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ TV ਨੂੰ ਹੌਲੀ ਕਰਦੇ ਹੋਏ ਹੋਰਾਂ ਐਪਸ ਤੇ ਉਪਲਬਧ ਮੈਮਰੀ ਨੂੰ ਸੀਮਿਤ ਕਰ ਸਕਦਾ ਹੈ।"</string>
-    <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"ਐਪ ਨੂੰ ਮੈਮਰੀ ਵਿੱਚ ਖੁਦ ਦੇ ਭਾਗਾਂ ਨੂੰ ਸਥਾਈ ਬਣਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਫੋਨ ਨੂੰ ਹੌਲੀ ਕਰਦੇ ਹੋਏ ਹੋਰਾਂ ਐਪਸ ਤੇ ਉਪਲਬਧ ਮੈਮਰੀ ਨੂੰ ਸੀਮਿਤ ਕਰ ਸਕਦਾ ਹੈ।"</string>
-    <string name="permlab_getPackageSize" msgid="7472921768357981986">"ਐਪ ਸਟੋਰੇਜ ਸਪੇਸ ਮਾਪੋ"</string>
-    <string name="permdesc_getPackageSize" msgid="3921068154420738296">"ਐਪ ਨੂੰ ਇਸਦਾ ਕੋਡ, ਡਾਟਾ ਅਤੇ ਕੈਸ਼ ਆਕਾਰ ਮੁੜ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+    <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"ਐਪ ਨੂੰ ਮੈਮਰੀ ਵਿੱਚ ਖੁਦ ਦੇ ਭਾਗਾਂ ਨੂੰ ਸਥਾਈ ਬਣਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਫ਼ੋਨ ਨੂੰ ਹੌਲੀ ਕਰਦੇ ਹੋਏ ਹੋਰਾਂ ਐਪਾਂ ਤੇ ਉਪਲਬਧ ਮੈਮਰੀ ਨੂੰ ਸੀਮਿਤ ਕਰ ਸਕਦਾ ਹੈ।"</string>
+    <string name="permlab_getPackageSize" msgid="7472921768357981986">"ਐਪ ਸਟੋਰੇਜ ਜਗ੍ਹਾ ਮਾਪੋ"</string>
+    <string name="permdesc_getPackageSize" msgid="3921068154420738296">"ਐਪ ਨੂੰ ਇਸਦਾ ਕੋਡ, ਡਾਟਾ ਅਤੇ ਕੈਸ਼ੇ ਆਕਾਰ ਮੁੜ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_writeSettings" msgid="2226195290955224730">"ਸਿਸਟਮ ਸੈਟਿੰਗਾਂ  ਸੰਸ਼ੋਧਿਤ ਕਰੋ"</string>
     <string name="permdesc_writeSettings" msgid="7775723441558907181">"ਐਪ ਨੂੰ ਸਿਸਟਮ ਦੇ ਸੈਟਿੰਗਾਂ ਡਾਟਾ ਨੂੰ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਖਰਾਬ ਐਪਾਂ ਤੁਹਾਡੇ ਸਿਸਟਮ ਦੀ ਸੰਰੂਪਣ ਨੂੰ ਕਰਪਟ ਕਰ ਸਕਦੇ ਹਨ।"</string>
     <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"ਚਾਲੂ ਹੋਣ ਤੇ ਚਲਾਓ"</string>
     <string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"ਐਪ ਨੂੰ ਸਿਸਟਮ ਦੇ ਬੂਟਿੰਗ ਖਤਮ ਕਰਨ ਦੇ ਤੁਰੰਤ ਬਾਅਦ ਖੁਦ ਚਾਲੂ ਹੋਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਚਾਲੂ ਹੋਣ ਵਿੱਚ ਥੋੜ੍ਹਾ ਵੱਧ ਸਮਾਂ ਲੱਗ ਸਕਦਾ ਹੈ ਅਤੇ ਇਹ ਐਪ ਨੂੰ ਹਮੇਸ਼ਾਂ ਚਲਾ ਕੇ ਸਮੁੱਚੇ ਟੈਬਲੈੱਟ ਨੂੰ ਹੌਲਾ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permdesc_receiveBootCompleted" product="tv" msgid="4525890122209673621">"ਐਪ ਨੂੰ ਸਿਸਟਮ ਦੇ ਬੂਟਿੰਗ ਖਤਮ ਕਰਨ ਦੇ ਤੁਰੰਤ ਬਾਅਦ ਖੁਦ ਚਾਲੂ ਹੋਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸ ਨਾਲ TV ਨੂੰ ਚਾਲੂ ਹੋਣ ਵਿੱਚ ਥੋੜ੍ਹਾ ਵੱਧ ਸਮਾਂ ਲੱਗ ਸਕਦਾ ਹੈ ਅਤੇ ਇਹ ਐਪ ਨੂੰ ਹਮੇਸ਼ਾਂ ਚਲਾ ਕੇ ਸਮੁੱਚੇ ਟੈਬਲੈੱਟ ਨੂੰ ਹੌਲਾ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
-    <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"ਐਪ ਨੂੰ ਸਿਸਟਮ ਦੇ ਬੂਟਿੰਗ ਖ਼ਤਮ ਕਰਨ ਦੇ ਤੁਰੰਤ ਬਾਅਦ ਖੁਦ ਚਾਲੂ ਹੋਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸ ਨਾਲ ਫੋਨ ਨੂੰ ਚਾਲੂ ਹੋਣ ਵਿੱਚ ਥੋੜ੍ਹਾ ਵੱਧ ਸਮਾਂ ਲੱਗ ਸਕਦਾ ਹੈ ਅਤੇ ਇਹ ਐਪ ਨੂੰ ਹਮੇਸ਼ਾਂ ਚਲਾ ਕੇ ਸਮੁੱਚੇ ਫੋਨ ਨੂੰ ਹੌਲਾ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+    <string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"ਐਪ ਨੂੰ ਸਿਸਟਮ ਦੇ ਬੂਟਿੰਗ ਖਤਮ ਕਰਨ ਦੇ ਤੁਰੰਤ ਬਾਅਦ ਖੁਦ ਚਾਲੂ ਹੋਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਚਾਲੂ ਹੋਣ ਵਿੱਚ ਥੋੜ੍ਹਾ ਵੱਧ ਸਮਾਂ ਲੱਗ ਸਕਦਾ ਹੈ ਅਤੇ ਇਹ ਐਪ ਨੂੰ ਹਮੇਸ਼ਾਂ ਚਲਾ ਕੇ ਸਮੁੱਚੇ ਫ਼ੋਨ ਨੂੰ ਹੌਲਾ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_broadcastSticky" msgid="7919126372606881614">"ਸਟਿਕੀ ਪ੍ਰਸਾਰਨ ਭੇਜੋ"</string>
     <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"ਐਪ ਨੂੰ ਸਟਿਕੀ ਪ੍ਰਸਾਰਨ ਭੇਜਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਜੋ ਪ੍ਰਸਾਰਨ ਦੇ ਖਤਮ ਹੋਣ ਤੋਂ ਬਾਅਦ ਰਹਿੰਦੇ ਹਨ। ਵਾਧੂ ਵਰਤੋਂ ਟੈਬਲੈੱਟ ਨੂੰ ਹੌਲੀ ਜਾਂ ਬਹੁਤ ਜ਼ਿਆਦਾ ਮੈਮਰੀ ਵਰਤ ਕੇ ਇਸਨੂੰ ਅਸਥਿਰ ਬਣਾ ਸਕਦੀ ਹੈ।"</string>
     <string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"ਐਪ ਨੂੰ ਸਟਿਕੀ ਪ੍ਰਸਾਰਨ ਭੇਜਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਜੋ ਪ੍ਰਸਾਰਨ ਦੇ ਖ਼ਤਮ ਹੋਣ ਤੋਂ ਬਾਅਦ ਰਹਿੰਦੇ ਹਨ। ਵਾਧੂ ਵਰਤੋਂ TV ਨੂੰ ਹੌਲੀ ਜਾਂ ਬਹੁਤ ਜ਼ਿਆਦਾ ਮੈਮਰੀ ਵਰਤ ਕੇ ਇਸਨੂੰ ਅਸਥਿਰ ਬਣਾ ਸਕਦੀ ਹੈ।"</string>
-    <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"ਐਪ ਨੂੰ ਸਟਿਕੀ ਪ੍ਰਸਾਰਨ ਭੇਜਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਜੋ ਪ੍ਰਸਾਰਨ ਦੇ ਖ਼ਤਮ ਹੋਣ ਤੋਂ ਬਾਅਦ ਰਹਿੰਦੇ ਹਨ। ਵਾਧੂ ਵਰਤੋਂ ਫੋਨ ਨੂੰ ਹੌਲੀ ਜਾਂ ਬਹੁਤ ਜ਼ਿਆਦਾ ਮੈਮਰੀ ਵਰਤ ਕੇ ਇਸਨੂੰ ਅਸਥਿਰ ਬਣਾ ਸਕਦੀ ਹੈ।"</string>
+    <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"ਐਪ ਨੂੰ ਸਟਿਕੀ ਪ੍ਰਸਾਰਨ ਭੇਜਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਜੋ ਪ੍ਰਸਾਰਨ ਦੇ ਖਤਮ ਹੋਣ ਤੋਂ ਬਾਅਦ ਰਹਿੰਦੇ ਹਨ। ਵਾਧੂ ਵਰਤੋਂ ਫ਼ੋਨ ਨੂੰ ਹੌਲੀ ਜਾਂ ਬਹੁਤ ਜ਼ਿਆਦਾ ਮੈਮਰੀ ਵਰਤ ਕੇ ਇਸਨੂੰ ਅਸਥਿਰ ਬਣਾ ਸਕਦੀ ਹੈ।"</string>
     <string name="permlab_readContacts" msgid="8348481131899886131">"ਆਪਣੇ ਸੰਪਰਕ ਪੜ੍ਹੋ"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ ਡਾਟਾ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਉਸ ਬਾਰੰਬਾਰਤਾ ਸਮੇਤ ਜਿਸ ਨਾਲ ਤੁਸੀਂ ਕਾਲ ਕੀਤੀ ਹੈ, ਈਮੇਲ ਕੀਤੀ ਹੈ ਜਾਂ ਖਾਸ ਵਿਅਕਤੀਆਂ ਨਾਲ ਹੋਰ ਤਰੀਕਿਆਂ ਨਾਲ ਸੰਚਾਰ ਕੀਤਾ ਹੈ। ਇਹ ਇਜਾਜ਼ਤ ਐਪਾਂ ਨੂੰ ਤੁਹਾਡਾ ਸੰਪਰਕ ਡਾਟਾ ਸੁਰੱਖਿਅਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ ਅਤੇ ਖਰਾਬ ਐਪਾਂ ਤੁਹਾਡੀ ਜਾਣਕਾਰੀ ਤੋਂ ਬਿਨਾਂ ਸੰਪਰਕ ਡਾਟਾ ਸਾਂਝਾ ਕਰ ਸਕਦੀਆਂ ਹਨ।"</string>
-    <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ TV ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ  ਡਾਟਾ  ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਉਸ ਬਾਰੰਬਾਰਤਾ ਸਮੇਤ ਜਿਸ ਨਾਲ ਤੁਸੀਂ ਕਾਲ ਕੀਤੀ ਹੈ, ਈਮੇਲ ਕੀਤੀ ਹੈ ਜਾਂ ਖ਼ਾਸ ਵਿਅਕਤੀਆਂ ਨਾਲ ਹੋਰ ਤਰੀਕਿਆਂ ਨਾਲ ਸੰਚਾਰ ਕੀਤਾ। ਇਹ ਅਨੁਮਤੀ ਐਪਸ ਨੂੰ ਤੁਹਾਡਾ ਸੰਪਰਕ  ਡਾਟਾ  ਸੁਰੱਖਿਅਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ ਅਤੇ ਖ਼ਰਾਬ ਐਪਸ ਤੁਹਾਡੀ ਜਾਣਕਾਰੀ ਤੋਂ ਬਿਨਾਂ ਸੰਪਰਕ  ਡਾਟਾ  ਸ਼ੇਅਰ ਕਰ ਸਕਦੇ ਹਨ।"</string>
-    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਫੋਨ ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ  ਡਾਟਾ  ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਉਸ ਬਾਰੰਬਾਰਤਾ ਸਮੇਤ ਜਿਸ ਨਾਲ ਤੁਸੀਂ ਕਾਲ ਕੀਤੀ ਹੈ, ਈਮੇਲ ਕੀਤੀ ਹੈ ਜਾਂ ਖ਼ਾਸ ਵਿਅਕਤੀਆਂ ਨਾਲ ਹੋਰ ਤਰੀਕਿਆਂ ਨਾਲ ਸੰਚਾਰ ਕੀਤਾ। ਇਹ ਅਨੁਮਤੀ ਐਪਸ ਨੂੰ ਤੁਹਾਡਾ ਸੰਪਰਕ  ਡਾਟਾ  ਸੁਰੱਖਿਅਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ ਅਤੇ ਖ਼ਰਾਬ ਐਪਸ ਤੁਹਾਡੀ ਜਾਣਕਾਰੀ ਤੋਂ ਬਿਨਾਂ ਸੰਪਰਕ  ਡਾਟਾ  ਸ਼ੇਅਰ ਕਰ ਸਕਦੇ ਹਨ।"</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ ਡਾਟਾ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਉਸ ਬਾਰੰਬਾਰਤਾ ਸਮੇਤ ਜਿਸ ਨਾਲ ਤੁਸੀਂ ਕਾਲ ਕੀਤੀ ਹੈ, ਈਮੇਲ ਕੀਤੀ ਹੈ ਜਾਂ ਖਾਸ ਵਿਅਕਤੀਆਂ ਨਾਲ ਹੋਰ ਤਰੀਕਿਆਂ ਨਾਲ ਸੰਚਾਰ ਕੀਤਾ ਹੈ। ਇਹ ਇਜਾਜ਼ਤ ਐਪਾਂ ਨੂੰ ਤੁਹਾਡਾ ਸੰਪਰਕ ਡਾਟਾ ਰੱਖਿਅਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ ਅਤੇ ਖਰਾਬ ਐਪਾਂ ਤੁਹਾਡੀ ਜਾਣਕਾਰੀ ਤੋਂ ਬਿਨਾਂ ਸੰਪਰਕ ਡਾਟਾ ਸਾਂਝਾ ਕਰ ਸਕਦੀਆਂ ਹਨ।"</string>
+    <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਟੀਵੀ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ ਡਾਟਾ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਉਸ ਬਾਰੰਬਾਰਤਾ ਸਮੇਤ ਜਿਸ ਨਾਲ ਤੁਸੀਂ ਕਾਲ ਕੀਤੀ ਹੈ, ਈਮੇਲ ਕੀਤੀ ਹੈ ਜਾਂ ਖਾਸ ਵਿਅਕਤੀਆਂ ਨਾਲ ਹੋਰ ਤਰੀਕਿਆਂ ਨਾਲ ਸੰਚਾਰ ਕੀਤਾ ਹੈ। ਇਹ ਇਜਾਜ਼ਤ ਐਪਾਂ ਨੂੰ ਤੁਹਾਡਾ ਸੰਪਰਕ ਡਾਟਾ ਰੱਖਿਅਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ ਅਤੇ ਖਰਾਬ ਐਪਾਂ ਤੁਹਾਡੀ ਜਾਣਕਾਰੀ ਤੋਂ ਬਿਨਾਂ ਸੰਪਰਕ ਡਾਟਾ ਸਾਂਝਾ ਕਰ ਸਕਦੀਆਂ ਹਨ।"</string>
+    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ ਡਾਟਾ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਉਸ ਬਾਰੰਬਾਰਤਾ ਸਮੇਤ ਜਿਸ ਨਾਲ ਤੁਸੀਂ ਕਾਲ ਕੀਤੀ ਹੈ, ਈਮੇਲ ਕੀਤੀ ਹੈ ਜਾਂ ਖਾਸ ਵਿਅਕਤੀਆਂ ਨਾਲ ਹੋਰ ਤਰੀਕਿਆਂ ਨਾਲ ਸੰਚਾਰ ਕੀਤਾ ਹੈ। ਇਹ ਇਜਾਜ਼ਤ ਐਪਾਂ ਨੂੰ ਤੁਹਾਡਾ ਸੰਪਰਕ ਡਾਟਾ ਰੱਖਿਅਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ ਅਤੇ ਖਰਾਬ ਐਪਾਂ ਤੁਹਾਡੀ ਜਾਣਕਾਰੀ ਤੋਂ ਬਿਨਾਂ ਸੰਪਰਕ ਡਾਟਾ ਸਾਂਝਾ ਕਰ ਸਕਦੀਆਂ ਹਨ।"</string>
     <string name="permlab_writeContacts" msgid="5107492086416793544">"ਆਪਣੇ ਸੰਪਰਕ ਸੰਸ਼ੋਧਿਤ ਕਰੋ"</string>
-    <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ ਡਾਟਾ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਉਸ ਬਾਰੰਬਾਰਤਾ ਸਮੇਤ ਜਿਸ ਨਾਲ ਤੁਸੀਂ ਕਾਲ ਕੀਤੀ ਹੈ, ਈਮੇਲ ਕੀਤੀ ਹੈ ਜਾਂ ਖਾਸ ਵਿਅਕਤੀਆਂ ਨਾਲ ਹੋਰ ਤਰੀਕਿਆਂ ਨਾਲ ਸੰਚਾਰ ਕੀਤਾ ਹੈ। ਇਹ ਇਜਾਜ਼ਤ ਐਪਾਂ ਨੂੰ ਸੰਪਰਕ ਡਾਟਾ ਮਿਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।"</string>
-    <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ TV ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ  ਡਾਟਾ  ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਉਸ ਬਾਰੰਬਾਰਤਾ ਸਮੇਤ ਜਿਸ ਨਾਲ ਤੁਸੀਂ ਕਾਲ ਕੀਤੀ ਹੈ, ਈਮੇਲ ਕੀਤੀ ਹੈ ਜਾਂ ਖ਼ਾਸ ਵਿਅਕਤੀਆਂ ਨਾਲ ਹੋਰ ਤਰੀਕਿਆਂ ਨਾਲ ਸੰਚਾਰ ਕੀਤਾ। ਇਹ ਅਨੁਮਤੀ ਐਪਸ ਨੂੰ ਸੰਪਰਕ  ਡਾਟਾ  ਮਿਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।"</string>
-    <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਫੋਨ ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ  ਡਾਟਾ  ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਉਸ ਬਾਰੰਬਾਰਤਾ ਸਮੇਤ ਜਿਸ ਨਾਲ ਤੁਸੀਂ ਕਾਲ ਕੀਤੀ ਹੈ, ਈਮੇਲ ਕੀਤੀ ਹੈ ਜਾਂ ਖ਼ਾਸ ਵਿਅਕਤੀਆਂ ਨਾਲ ਹੋਰ ਤਰੀਕਿਆਂ ਨਾਲ ਸੰਚਾਰ ਕੀਤਾ। ਇਹ ਅਨੁਮਤੀ ਐਪਸ ਨੂੰ ਤੁਹਾਡਾ ਸੰਪਰਕ  ਡਾਟਾ  ਮਿਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।"</string>
+    <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"ਐਪ ਨੂੰ ਤੁਹਾਡੀ ਟੈਬਲੈੱਟ ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ ਡਾਟਾ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਉਸ ਬਾਰੰਬਾਰਤਾ ਸਮੇਤ ਜਿਸ ਨਾਲ ਤੁਸੀਂ ਕਾਲ ਕੀਤੀ ਹੈ, ਈਮੇਲ ਕੀਤੀ ਹੈ ਜਾਂ ਖ਼ਾਸ ਵਿਅਕਤੀਆਂ ਨਾਲ ਹੋਰ ਤਰੀਕਿਆਂ ਨਾਲ ਸੰਚਾਰ ਕੀਤਾ। ਇਹ ਇਜਾਜ਼ਤ ਐਪਾਂ ਨੂੰ ਸੰਪਰਕ ਡਾਟਾ ਮਿਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।"</string>
+    <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਟੀਵੀ ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ ਡਾਟਾ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਉਸ ਬਾਰੰਬਾਰਤਾ ਸਮੇਤ ਜਿਸ ਨਾਲ ਤੁਸੀਂ ਕਾਲ ਕੀਤੀ ਹੈ, ਈਮੇਲ ਕੀਤੀ ਹੈ ਜਾਂ ਖ਼ਾਸ ਵਿਅਕਤੀਆਂ ਨਾਲ ਹੋਰ ਤਰੀਕਿਆਂ ਨਾਲ ਸੰਚਾਰ ਕੀਤਾ। ਇਹ ਇਜਾਜ਼ਤ ਐਪਾਂ ਨੂੰ ਸੰਪਰਕ ਡਾਟਾ ਮਿਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।"</string>
+    <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਤੇ ਸਟੋਰ ਕੀਤੇ ਤੁਹਾਡੇ ਸੰਪਰਕਾਂ ਬਾਰੇ ਡਾਟਾ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਉਸ ਬਾਰੰਬਾਰਤਾ ਸਮੇਤ ਜਿਸ ਨਾਲ ਤੁਸੀਂ ਕਾਲ ਕੀਤੀ ਹੈ, ਈਮੇਲ ਕੀਤੀ ਹੈ ਜਾਂ ਖ਼ਾਸ ਵਿਅਕਤੀਆਂ ਨਾਲ ਹੋਰ ਤਰੀਕਿਆਂ ਨਾਲ ਸੰਚਾਰ ਕੀਤਾ। ਇਹ ਇਜਾਜ਼ਤ ਐਪਾਂ ਨੂੰ ਤੁਹਾਡਾ ਸੰਪਰਕ ਡਾਟਾ ਮਿਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।"</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"ਕਾਲ ਲੌਗ ਪੜ੍ਹੋ"</string>
     <string name="permdesc_readCallLog" msgid="3204122446463552146">"ਇਹ ਐਪ ਤੁਹਾਡਾ ਕਾਲ ਇਤਿਹਾਸ ਪੜ੍ਹ ਸਕਦੀ ਹੈ।"</string>
     <string name="permlab_writeCallLog" msgid="8552045664743499354">"ਕਾਲ ਲੌਗ ਲਿਖੋ"</string>
     <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ ਦਾ ਕਾਲ ਲੌਗ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਇਨਕਮਿੰਗ ਅਤੇ ਆਊਟਗੋਇੰਗ ਕਾਲਾਂ ਬਾਰੇ ਡਾਟਾ ਸਮੇਤ। ਖਰਾਬ ਐਪਾਂ ਇਸਦੀ ਵਰਤੋਂ ਤੁਹਾਡੇ ਕਾਲ ਲੌਗ ਨੂੰ ਮਿਟਾਉਣ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਲਈ ਕਰ ਸਕਦੀਆਂ ਹਨ।"</string>
-    <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ TV ਦਾ ਕਾਲ ਲੌਗ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਇਨਕਮਿੰਗ ਅਤੇ ਆਊਟਗੋਇੰਗ ਕਾਲਾਂ ਬਾਰੇ ਡਾਟਾ ਸਮੇਤ। ਖਰਾਬ ਐਪਾਂ ਇਸਦੀ ਵਰਤੋਂ ਤੁਹਾਡੇ ਕਾਲ ਲੌਗ ਨੂੰ ਮਿਟਾਉਣ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਲਈ ਕਰ ਸਕਦੀਆਂ ਹਨ।"</string>
+    <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਟੀਵੀ ਦਾ ਕਾਲ ਲੌਗ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਇਨਕਮਿੰਗ ਅਤੇ ਆਊਟਗੋਇੰਗ ਕਾਲਾਂ ਬਾਰੇ ਡਾਟਾ ਸਮੇਤ। ਖਰਾਬ ਐਪਾਂ ਇਸਦੀ ਵਰਤੋਂ ਤੁਹਾਡੇ ਕਾਲ ਲੌਗ ਨੂੰ ਮਿਟਾਉਣ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਲਈ ਕਰ ਸਕਦੀਆਂ ਹਨ।"</string>
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਨ ਦਾ ਕਾਲ ਲੌਗ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਇਨਕਮਿੰਗ ਅਤੇ ਆਊਟਗੋਇੰਗ ਕਾਲਾਂ ਬਾਰੇ ਡਾਟਾ ਸਮੇਤ। ਖਰਾਬ ਐਪਾਂ ਇਸਦੀ ਵਰਤੋਂ ਤੁਹਾਡੇ ਕਾਲ ਲੌਗ ਨੂੰ ਮਿਟਾਉਣ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਲਈ ਕਰ ਸਕਦੀਆਂ ਹਨ।"</string>
     <string name="permlab_bodySensors" msgid="4683341291818520277">"ਸਰੀਰ ਸੰਵੇਦਕਾਂ \'ਤੇ ਪਹੁੰਚ ਕਰੋ (ਜਿਵੇਂ ਦਿਲ ਦੀ ਧੜਕਣ ਦੇ ਨਿਰੀਖਕ)"</string>
     <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"ਐਪ ਨੂੰ ਉਹਨਾਂ ਸੰਵੇਦਕਾਂ ਦੇ ਡਾਟਾ ਤੱਕ ਪਹੁੰਚ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ ਜੋ ਤੁਹਾਡੀ ਸਰੀਰਕ ਸਥਿਤੀ ਦਾ ਨਿਰੀਖਣ ਕਰ ਸਕਦੇ ਹਨ, ਜਿਵੇਂ ਤੁਹਾਡੇ ਦਿਲ ਦੀ ਧੜਕਣ।"</string>
     <string name="permlab_readCalendar" msgid="6716116972752441641">"ਕੈਲੰਡਰ ਵਰਤਾਰਿਆਂ ਅਤੇ ਵੇਰਵਿਆਂ ਨੂੰ ਪੜ੍ਹੋ"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="4993979255403945892">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ ਉੱਤੇ ਸਟੋਰ ਕੀਤੇ ਸਾਰੇ ਕੈਲੰਡਰ ਇਵੈਂਟਾਂ ਨੂੰ ਪੜ੍ਹ ਸਕਦੀ ਹੈ ਅਤੇ ਤੁਹਾਡੇ ਕੈਲੰਡਰ ਡਾਟੇ ਨੂੰ ਸਾਂਝਾ ਜਾਂ ਰੱਖਿਅਤ ਕਰ ਸਕਦੀ ਹੈ।"</string>
-    <string name="permdesc_readCalendar" product="tv" msgid="8837931557573064315">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਟੀਵੀ ਉੱਤੇ ਸਟੋਰ ਕੀਤੇ ਸਾਰੇ ਕੈਲੰਡਰ ਵਰਤਾਰਿਆਂ ਨੂੰ ਪੜ੍ਹ ਸਕਦੀ ਹੈ ਅਤੇ ਤੁਹਾਡੇ ਕੈਲੰਡਰ ਡੈਟੇ ਨੂੰ ਸਾਂਝਾ ਜਾਂ ਰੱਖਿਅਤ ਕਰ ਸਕਦੀ ਹੈ।"</string>
-    <string name="permdesc_readCalendar" product="default" msgid="4373978642145196715">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਫ਼ੋਨ ਉੱਤੇ ਸਟੋਰ ਕੀਤੇ ਸਾਰੇ ਕੈਲੰਡਰ ਵਰਤਾਰਿਆਂ ਨੂੰ ਪੜ੍ਹ ਸਕਦੀ ਹੈ ਅਤੇ ਤੁਹਾਡੇ ਕੈਲੰਡਰ ਡੈਟੇ ਨੂੰ ਸਾਂਝਾ ਜਾਂ ਰੱਖਿਅਤ ਕਰ ਸਕਦੀ ਹੈ।"</string>
-    <string name="permlab_writeCalendar" msgid="8438874755193825647">"ਕੈਲੰਡਰ ਇਵੈਂਟਾਂ ਜੋੜੋ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰੋ ਅਤੇ ਮਾਲਕ ਦੀ ਜਾਣਕਾਰੀ ਤੋਂ ਬਿਨਾਂ ਮਹਿਮਾਨਾਂ ਨੂੰ ਈਮੇਲ ਭੇਜੋ"</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="4993979255403945892">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਸਾਰੇ ਕੈਲੰਡਰ ਇਵੈਂਟਾਂ ਨੂੰ ਪੜ੍ਹ ਸਕਦੀ ਹੈ ਅਤੇ ਤੁਹਾਡੇ ਕੈਲੰਡਰ ਡਾਟੇ ਨੂੰ ਸਾਂਝਾ ਜਾਂ ਰੱਖਿਅਤ ਕਰ ਸਕਦੀ ਹੈ।"</string>
+    <string name="permdesc_readCalendar" product="tv" msgid="8837931557573064315">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਟੀਵੀ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਸਾਰੇ ਕੈਲੰਡਰ ਇਵੈਂਟਾਂ ਨੂੰ ਪੜ੍ਹ ਸਕਦੀ ਹੈ ਅਤੇ ਤੁਹਾਡੇ ਕੈਲੰਡਰ ਡਾਟੇ ਨੂੰ ਸਾਂਝਾ ਜਾਂ ਰੱਖਿਅਤ ਕਰ ਸਕਦੀ ਹੈ।"</string>
+    <string name="permdesc_readCalendar" product="default" msgid="4373978642145196715">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਸਟੋਰ ਕੀਤੇ ਸਾਰੇ ਕੈਲੰਡਰ ਇਵੈਂਟਾਂ ਨੂੰ ਪੜ੍ਹ ਸਕਦੀ ਹੈ ਅਤੇ ਤੁਹਾਡੇ ਕੈਲੰਡਰ ਡਾਟੇ ਨੂੰ ਸਾਂਝਾ ਜਾਂ ਰੱਖਿਅਤ ਕਰ ਸਕਦੀ ਹੈ।"</string>
+    <string name="permlab_writeCalendar" msgid="8438874755193825647">"ਕੈਲੰਡਰ ਇਵੈਂਟ ਸ਼ਾਮਲ ਕਰੋ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰੋ ਅਤੇ ਮਾਲਕ ਦੀ ਜਾਣਕਾਰੀ ਤੋਂ ਬਿਨਾਂ ਮਹਿਮਾਨਾਂ ਨੂੰ ਈਮੇਲ ਭੇਜੋ"</string>
     <string name="permdesc_writeCalendar" product="tablet" msgid="1675270619903625982">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ \'ਤੇ ਕੈਲੰਡਰ ਇਵੈਂਟਾਂ ਨੂੰ ਸ਼ਾਮਲ ਕਰ ਸਕਦੀ ਹੈ, ਹਟਾ ਸਕਦੀ ਹੈ, ਜਾਂ ਬਦਲ ਸਕਦੀ ਹੈ। ਇਹ ਐਪ ਉਹਨਾਂ ਸੁਨੇਹਿਆਂ ਨੂੰ ਭੇਜ ਸਕਦੀ ਹੈ ਜੋ ਕਿ ਕੈਲੰਡਰ ਮਾਲਕਾਂ ਤੋਂ ਆਉਂਦੇ ਜਾਪ ਸਕਦੇ ਹਨ, ਜਾਂ ਉਹਨਾਂ ਦੇ ਮਾਲਕਾਂ ਨੂੰ ਸੂਚਿਤ ਕੀਤੇ ਬਿਨਾਂ ਇਵੈਂਟਾਂ ਨੂੰ ਬਦਲ ਸਕਦੀ ਹੈ।"</string>
-    <string name="permdesc_writeCalendar" product="tv" msgid="9017809326268135866">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਟੀਵੀ \'ਤੇ ਕੈਲੰਡਰ ਵਰਤਾਰਿਆਂ ਨੂੰ ਸ਼ਾਮਲ ਕਰ ਸਕਦੀ ਹੈ, ਹਟਾ ਸਕਦੀ ਹੈ, ਜਾਂ ਬਦਲ ਸਕਦੀ ਹੈ। ਇਹ ਐਪ ਉਹਨਾਂ ਸੁਨੇਹਿਆਂ ਨੂੰ ਭੇਜ ਸਕਦੀ ਹੈ ਜੋ ਕੈਲੰਡਰ ਮਾਲਕਾਂ ਤੋਂ ਆਉਂਦੇ ਜਾਪ ਸਕਦੇ ਹਨ, ਜਾਂ ਉਹਨਾਂ ਦੇ ਮਾਲਕਾਂ ਨੂੰ ਸੂਚਿਤ ਕੀਤੇ ਬਿਨਾਂ ਵਰਤਾਰਿਆਂ ਨੂੰ ਬਦਲ ਸਕਦੀ ਹੈ।"</string>
-    <string name="permdesc_writeCalendar" product="default" msgid="7592791790516943173">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਕੈਲੰਡਰ ਵਰਤਾਰਿਆਂ ਨੂੰ ਸ਼ਾਮਲ ਕਰ ਸਕਦੀ ਹੈ, ਹਟਾ ਸਕਦੀ ਹੈ, ਜਾਂ ਬਦਲ ਸਕਦੀ ਹੈ। ਇਹ ਐਪ ਉਹਨਾਂ ਸੁਨੇਹਿਆਂ ਨੂੰ ਭੇਜ ਸਕਦੀ ਹੈ ਜੋ ਕੈਲੰਡਰ ਮਾਲਕਾਂ ਤੋਂ ਆਉਂਦੇ ਜਾਪ ਸਕਦੇ ਹਨ, ਜਾਂ ਉਹਨਾਂ ਦੇ ਮਾਲਕਾਂ ਨੂੰ ਸੂਚਿਤ ਕੀਤੇ ਬਿਨਾਂ ਵਰਤਾਰਿਆਂ ਨੂੰ ਬਦਲ ਸਕਦੀ ਹੈ।"</string>
+    <string name="permdesc_writeCalendar" product="tv" msgid="9017809326268135866">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਟੀਵੀ \'ਤੇ ਕੈਲੰਡਰ ਇਵੈਂਟਾਂ ਨੂੰ ਸ਼ਾਮਲ ਕਰ ਸਕਦੀ ਹੈ, ਹਟਾ ਸਕਦੀ ਹੈ, ਜਾਂ ਬਦਲ ਸਕਦੀ ਹੈ। ਇਹ ਐਪ ਉਹਨਾਂ ਸੁਨੇਹਿਆਂ ਨੂੰ ਭੇਜ ਸਕਦੀ ਹੈ ਜੋ ਕੈਲੰਡਰ ਮਾਲਕਾਂ ਤੋਂ ਆਉਂਦੇ ਜਾਪ ਸਕਦੇ ਹਨ, ਜਾਂ ਉਹਨਾਂ ਦੇ ਮਾਲਕਾਂ ਨੂੰ ਸੂਚਿਤ ਕੀਤੇ ਬਿਨਾਂ ਇਵੈਂਟਾਂ ਨੂੰ ਬਦਲ ਸਕਦੀ ਹੈ।"</string>
+    <string name="permdesc_writeCalendar" product="default" msgid="7592791790516943173">"ਇਹ ਐਪ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਕੈਲੰਡਰ ਇਵੈਂਟਾਂ ਨੂੰ ਸ਼ਾਮਲ ਕਰ ਸਕਦੀ ਹੈ, ਹਟਾ ਸਕਦੀ ਹੈ, ਜਾਂ ਬਦਲ ਸਕਦੀ ਹੈ। ਇਹ ਐਪ ਉਹਨਾਂ ਸੁਨੇਹਿਆਂ ਨੂੰ ਭੇਜ ਸਕਦੀ ਹੈ ਜੋ ਕੈਲੰਡਰ ਮਾਲਕਾਂ ਤੋਂ ਆਉਂਦੇ ਜਾਪ ਸਕਦੇ ਹਨ, ਜਾਂ ਉਹਨਾਂ ਦੇ ਮਾਲਕਾਂ ਨੂੰ ਸੂਚਿਤ ਕੀਤੇ ਬਿਨਾਂ ਇਵੈਂਟਾਂ ਨੂੰ ਬਦਲ ਸਕਦੀ ਹੈ।"</string>
     <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"ਵਾਧੂ ਟਿਕਾਣਾ ਪ੍ਰਦਾਤਾ ਕਮਾਂਡਾਂ ਤੱਕ ਪਹੁੰਚ"</string>
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"ਐਪ ਨੂੰ ਵਾਧੂ ਟਿਕਾਣਾ ਪ੍ਰਦਾਤਾ ਕਮਾਂਡਾਂ ਤੱਕ ਪਹੁੰਚ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਐਪ ਨੂੰ GPS ਜਾਂ ਹੋਰ ਟਿਕਾਣਾ ਸਰੋਤਾਂ ਦੇ ਓਪਰੇਸ਼ਨ ਵਿੱਚ ਵਿਘਨ ਪਾਉਣ ਦੀ ਆਗਿਆ ਦੇ ਸਕਦਾ ਹੈ।"</string>
     <string name="permlab_accessFineLocation" msgid="251034415460950944">"ਸਟੀਕ ਟਿਕਾਣੇ \'ਤੇ ਪਹੁੰਚ ਕਰੋ (GPS ਅਤੇ ਨੈੱਟਵਰਕ-ਆਧਾਰਿਤ)"</string>
-    <string name="permdesc_accessFineLocation" msgid="5821994817969957884">"ਇਹ ਐਪ GPS ਜਾਂ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਵੱਲੋਂ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ। ਇਸ ਨਾਲ ਬੈਟਰੀ ਦੀ ਖਪਤ ਵਧ ਸਕਦੀ ਹੈ।"</string>
+    <string name="permdesc_accessFineLocation" msgid="5821994817969957884">"ਇਹ ਐਪ GPS ਜਾਂ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਦੁਆਰਾ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ। ਇਸ ਨਾਲ ਬੈਟਰੀ ਦੀ ਖਪਤ ਵਧ ਸਕਦੀ ਹੈ।"</string>
     <string name="permlab_accessCoarseLocation" msgid="7715277613928539434">"ਅੰਦਾਜ਼ਨ ਟਿਕਾਣੇ \'ਤੇ ਪਹੁੰਚ ਕਰੋ (ਨੈੱਟਵਰਕ-ਆਧਾਰਿਤ)"</string>
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"ਇਹ ਐਪ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਦੁਆਰਾ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ।"</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"ਇਹ ਐਪ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਵੱਲੋਂ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਟੀਵੀ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ।"</string>
@@ -395,22 +395,22 @@
     <string name="permdesc_callPhone" msgid="3740797576113760827">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਦਖਲ ਤੋਂ ਬਿਨਾਂ ਫ਼ੋਨ ਨੰਬਰਾਂ ਤੇ ਕਾਲ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸਦੇ ਸਿੱਟੇ ਵਜੋਂ ਅਕਲਪਿਤ ਖਰਚੇ ਜਾਂ ਕਾਲਾਂ ਹੋ ਸਕਦੀਆਂ ਹਨ। ਧਿਆਨ ਦਿਓ ਕਿ ਇਹ ਐਪ ਨੂੰ ਸੰਕਟਕਾਲੀਨ ਨੰਬਰਾਂ ਤੇ ਕਾਲ ਕਰਨ ਦੀ ਆਗਿਆ ਨਹੀਂ ਦਿੰਦਾ। ਖਰਾਬ ਐਪਾਂ ਤੁਹਾਡੀ ਪੁਸ਼ਟੀ ਤੋਂ ਬਿਨਾਂ ਕਾਲਾਂ ਕਰਕੇ ਤੁਹਾਨੂੰ ਖਰਚੇ ਪਾ ਸਕਦੀਆਂ ਹਨ।"</string>
     <string name="permlab_accessImsCallService" msgid="3574943847181793918">"IMS ਕਾਲ ਸੇਵਾ ਤੱਕ ਪਹੁੰਚ"</string>
     <string name="permdesc_accessImsCallService" msgid="8992884015198298775">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਦਖ਼ਲ ਤੋਂ ਬਿਨਾਂ ਕਾਲਾਂ ਕਰਨ ਲਈ IMS ਸੇਵਾ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।"</string>
-    <string name="permlab_readPhoneState" msgid="9178228524507610486">"ਫੋਨ ਸਥਿਤੀ ਅਤੇ ਪਛਾਣ ਪੜ੍ਹੋ"</string>
-    <string name="permdesc_readPhoneState" msgid="1639212771826125528">"ਐਪ ਨੂੰ ਡੀਵਾਈਸ ਦੀਆਂ ਫ਼ੋਨ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਤੱਕ ਪਹੁੰਚ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਇਜਾਜ਼ਤ ਐਪ ਨੂੰ ਫ਼ੋਨ ਨੰਬਰ ਅਤੇ ਡੀਵਾਈਸ ਆਈ.ਡੀ. ਨਿਰਧਾਰਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ, ਇੱਕ ਕਾਲ ਕਿਰਿਆਸ਼ੀਲ ਹੈ ਜਾਂ ਨਹੀਂ ਅਤੇ ਰਿਮੋਟ ਨੰਬਰ ਇੱਕ ਕਾਲ ਨਾਲ ਕਨੈਕਟ ਹੈ ਜਾਂ ਨਹੀਂ।"</string>
+    <string name="permlab_readPhoneState" msgid="9178228524507610486">"ਫ਼ੋਨ ਸਥਿਤੀ ਅਤੇ ਪਛਾਣ ਪੜ੍ਹੋ"</string>
+    <string name="permdesc_readPhoneState" msgid="1639212771826125528">"ਐਪ ਨੂੰ ਡੀਵਾਈਸ ਦੀਆਂ ਫ਼ੋਨ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਤੱਕ ਪਹੁੰਚ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਇਜਾਜ਼ਤ ਐਪ ਨੂੰ ਫ਼ੋਨ ਨੰਬਰ ਅਤੇ ਡੀਵਾਈਸ ਆਈ.ਡੀ. ਨਿਰਧਾਰਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ, ਇੱਕ ਕਾਲ ਕਿਰਿਆਸ਼ੀਲ ਹੈ ਜਾਂ ਨਹੀਂ ਅਤੇ ਰਿਮੋਟ ਨੰਬਰ ਇੱਕ ਕਾਲ ਨਾਲ ਕਨੈਕਟ ਹੈ ਜਾਂ ਨਹੀਂ।"</string>
     <string name="permlab_manageOwnCalls" msgid="1503034913274622244">"ਸਿਸਟਮ ਰਾਹੀਂ ਕਾਲਾਂ ਰੂਟ ਕਰੋ"</string>
     <string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"ਕਾਲ ਕਰਨ ਦੇ ਅਨੁਭਵ ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਣ ਲਈ ਐਪ ਨੂੰ ਇਸਦੀਆਂ ਕਾਲਾਂ ਨੂੰ ਸਿਸਟਮ ਰਾਹੀਂ ਰੂਟ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿੰਦੀ ਹੈ।"</string>
     <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"ਫ਼ੋਨ ਨੰਬਰ ਪੜ੍ਹੋ"</string>
-    <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"ਐਪ ਨੂੰ ਡੀਵਾਈਸ ਦੇ ਫ਼ੋਨ ਨੰਬਰਾਂ \'ਤੇ ਪਹੁੰਚ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।"</string>
+    <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"ਐਪ ਨੂੰ ਡੀਵਾਈਸ ਦੇ ਫ਼ੋਨ ਨੰਬਰਾਂ \'ਤੇ ਪਹੁੰਚ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿੰਦੀ ਹੈ।"</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"ਟੈਬਲੈੱਟ ਨੂੰ ਸਲੀਪ ਤੇ ਜਾਣ ਤੋਂ ਰੋਕੋ"</string>
     <string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"TV ਨੂੰ ਸਲੀਪਿੰਗ ਤੋਂ ਰੋਕੋ"</string>
-    <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ਫੋਨ ਨੂੰ ਸਲੀਪਿੰਗ ਤੋਂ ਰੋਕੋ"</string>
+    <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"ਫ਼ੋਨ ਨੂੰ ਸਲੀਪਿੰਗ ਤੋਂ ਰੋਕੋ"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"ਐਪ ਨੂੰ ਟੈਬਲੈੱਟ ਨੂੰ ਸਲੀਪ ਤੇ ਜਾਣ ਤੋਂ ਰੋਕਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permdesc_wakeLock" product="tv" msgid="3208534859208996974">"ਐਪ ਨੂੰ TV ਨੂੰ ਸਲੀਪ ਤੇ ਜਾਣ ਤੋਂ ਰੋਕਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
-    <string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"ਐਪ ਨੂੰ ਫੋਨ ਨੂੰ ਸਲੀਪ ਤੇ ਜਾਣ ਤੋਂ ਰੋਕਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+    <string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"ਐਪ ਨੂੰ ਫ਼ੋਨ ਨੂੰ ਸਲੀਪ ਤੇ ਜਾਣ ਤੋਂ ਰੋਕਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_transmitIr" msgid="7545858504238530105">"ਇੰਫ੍ਰਾਰੈਡ ਟ੍ਰਾਂਸਮਿਟ ਕਰੋ"</string>
     <string name="permdesc_transmitIr" product="tablet" msgid="5358308854306529170">"ਐਪ ਨੂੰ ਟੈਬਲੈੱਟ ਦਾ ਇੰਫਰਾਰੈਡ ਟ੍ਰਾਂਸਮੀਟਰ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permdesc_transmitIr" product="tv" msgid="3926790828514867101">"ਐਪ ਨੂੰ TV ਦਾ ਇੰਫਰਾਰੈਡ ਟ੍ਰਾਂਸਮੀਟਰ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
-    <string name="permdesc_transmitIr" product="default" msgid="7957763745020300725">"ਐਪ ਨੂੰ ਫੋਨ ਦਾ ਇੰਫਰਾਰੈਡ ਟ੍ਰਾਂਸਮੀਟਰ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+    <string name="permdesc_transmitIr" product="default" msgid="7957763745020300725">"ਐਪ ਨੂੰ ਫ਼ੋਨ ਦਾ ਇੰਫਰਾਰੈਡ ਟ੍ਰਾਂਸਮੀਟਰ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_setWallpaper" msgid="6627192333373465143">"ਵਾਲਪੇਪਰ ਸੈੱਟ ਕਰੋ"</string>
     <string name="permdesc_setWallpaper" msgid="7373447920977624745">"ਐਪ ਨੂੰ ਸਿਸਟਮ ਵਾਲਪੇਪਰ ਸੈਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_setWallpaperHints" msgid="3278608165977736538">"ਆਪਣਾ ਵਾਲਪੇਪਰ ਆਕਾਰ ਵਿਵਸਥਿਤ ਕਰੋ"</string>
@@ -418,15 +418,15 @@
     <string name="permlab_setTimeZone" msgid="2945079801013077340">"ਸਮਾਂ ਜ਼ੋਨ ਸੈੱਟ ਕਰੋ"</string>
     <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"ਐਪ ਨੂੰ ਟੈਬਲੈੱਟ ਦਾ ਸਮਾਂ ਜ਼ੋਨ ਬਦਲਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permdesc_setTimeZone" product="tv" msgid="888864653946175955">"ਐਪ ਨੂੰ TV ਦਾ ਸਮਾਂ ਜ਼ੋਨ ਬਦਲਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
-    <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"ਐਪ ਨੂੰ ਫੋਨ ਦਾ ਸਮਾਂ ਜ਼ੋਨ ਬਦਲਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+    <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"ਐਪ ਨੂੰ ਫ਼ੋਨ ਦਾ ਸਮਾਂ ਜ਼ੋਨ ਬਦਲਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_getAccounts" msgid="1086795467760122114">"ਡੀਵਾਈਸ ਤੇ ਖਾਤੇ ਲੱਭੋ"</string>
     <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"ਐਪ ਨੂੰ ਟੈਬਲੈੱਟ ਵੱਲੋਂ ਗਿਆਤ ਖਾਤਿਆਂ ਦੀ ਸੂਚੀ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸ ਵਿੱਚ ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਥਾਪਤ ਕੀਤੀਆਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਦੁਆਰਾ ਬਣਾਏ ਗਏ ਕੋਈ ਵੀ ਖਾਤੇ ਸ਼ਾਮਲ ਹੋ ਸਕਦੇ ਹਨ।"</string>
     <string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"ਐਪ ਨੂੰ TV ਵੱਲੋਂ ਗਿਆਤ ਖਾਤਿਆਂ ਦੀ ਸੂਚੀ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸ ਵਿੱਚ ਤੁਹਾਡੇ ਵੱਲੋਂ ਇੰਸਟੌਲ ਕੀਤੀਆਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਵੱਲੋਂ ਬਣਾਏ ਗਏ ਕੋਈ ਵੀ ਖਾਤੇ ਸ਼ਾਮਲ ਹੋ ਸਕਦੇ ਹਨ।"</string>
-    <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"ਐਪ ਨੂੰ ਫੋਨ ਵੱਲੋਂ ਗਿਆਤ ਖਾਤਿਆਂ ਦੀ ਸੂਚੀ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸ ਵਿੱਚ ਤੁਹਾਡੇ ਵੱਲੋਂ ਇੰਸਟੌਲ ਕੀਤੀਆਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਵੱਲੋਂ ਬਣਾਏ ਗਏ ਕੋਈ ਵੀ ਖਾਤੇ ਸ਼ਾਮਲ ਹੋ ਸਕਦੇ ਹਨ।"</string>
+    <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"ਐਪ ਨੂੰ ਫ਼ੋਨ ਵੱਲੋਂ ਗਿਆਤ ਖਾਤਿਆਂ ਦੀ ਸੂਚੀ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸ ਵਿੱਚ ਤੁਹਾਡੇ ਵੱਲੋਂ ਸਥਾਪਤ ਕੀਤੀਆਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਵੱਲੋਂ ਬਣਾਏ ਗਏ ਕੋਈ ਵੀ ਖਾਤੇ ਸ਼ਾਮਲ ਹੋ ਸਕਦੇ ਹਨ।"</string>
     <string name="permlab_accessNetworkState" msgid="4951027964348974773">"ਨੈੱਟਵਰਕ ਕਨੈਕਸ਼ਨ ਦੇਖੋ"</string>
     <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"ਐਪ ਨੂੰ ਨੈੱਟਵਰਕ ਕਨੈਕਸ਼ਨਾਂ ਬਾਰੇ ਜਾਣਕਾਰੀ ਦੇਖਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ ਜਿਵੇਂ ਕਿਹੜੇ ਨੈੱਟਵਰਕ ਮੌਜੂਦ ਹਨ ਅਤੇ ਕਨੈਕਟ ਕੀਤੇ ਹੋਏ ਹਨ।"</string>
     <string name="permlab_createNetworkSockets" msgid="7934516631384168107">"ਪੂਰੀ ਨੈੱਟਵਰਕ ਪਹੁੰਚ ਪਾਓ"</string>
-    <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"ਐਪ ਨੂੰ ਨੈੱਟਵਰਕ ਸੌਕੇਟ ਬਣਾਉਣ ਅਤੇ ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ ਨੈੱਟਵਰਕ ਪ੍ਰੋਟੋਕੋਲ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਬ੍ਰਾਊਜ਼ਰ ਅਤੇ ਹੋਰ ਐਪਲੀਕੇਸ਼ਨਾਂ ਇੰਟਰਨੈੱਟ ਨੂੰ ਡਾਟਾ ਭੇਜਣ ਲਈ ਸਾਧਨ ਮੁਹੱਈਆ ਕਰਦਾ ਹੈ, ਇਸਲਈ ਇੰਟਰਨੈੱਟ ਡਾਟਾ ਭੇਜਣ ਲਈ ਇਹ ਅਨੁਮਤੀ ਲੁੜੀਂਦੀ ਨਹੀਂ ਹੈ।"</string>
+    <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"ਐਪ ਨੂੰ ਨੈੱਟਵਰਕ ਸਾਕੇਟ ਬਣਾਉਣ ਅਤੇ ਕਸਟਮ ਨੈੱਟਵਰਕ ਪ੍ਰੋਟੋਕੋਲ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਬ੍ਰਾਊਜ਼ਰ ਅਤੇ ਹੋਰ ਐਪਲੀਕੇਸ਼ਨਾਂ ਇੰਟਰਨੈੱਟ ਨੂੰ ਡਾਟਾ ਭੇਜਣ ਲਈ ਸਾਧਨ ਮੁਹੱਈਆ ਕਰਦੀਆਂ ਹਨ, ਇਸ ਲਈ ਇੰਟਰਨੈੱਟ ਡਾਟਾ ਭੇਜਣ ਲਈ ਇਹ ਅਨੁਮਤੀ ਲੋੜੀਂਦੀ ਨਹੀਂ ਹੈ।"</string>
     <string name="permlab_changeNetworkState" msgid="958884291454327309">"ਨੈੱਟਵਰਕ ਕਨੈਕਟੀਵਿਟੀ ਬਦਲੋ"</string>
     <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"ਐਪ ਨੂੰ ਨੈੱਟਵਰਕ ਕਨੈਕਟੀਵਿਟੀ ਦੀ ਸਥਿਤੀ ਬਦਲਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_changeTetherState" msgid="5952584964373017960">"ਟੀਥਰ ਕੀਤੀ ਕਨੈਕਟੀਵਿਟੀ ਬਦਲੋ"</string>
@@ -434,31 +434,31 @@
     <string name="permlab_accessWifiState" msgid="5202012949247040011">"ਵਾਈ-ਫਾਈ ਕਨੈਕਸ਼ਨ ਦੇਖੋ"</string>
     <string name="permdesc_accessWifiState" msgid="5002798077387803726">"ਐਪ ਨੂੰ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਿੰਗ ਬਾਰੇ ਜਾਣਕਾਰੀ ਦੇਖਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਜਿਵੇਂ ਵਾਈ-ਫਾਈ ਸਮਰਥਿਤ ਹੈ ਜਾਂ ਨਹੀਂ ਅਤੇ ਕਨੈਕਟ ਕੀਤੇ ਵਾਈ-ਫਾਈ ਡੀਵਾਈਸਾਂ ਦਾ ਨਾਮ।"</string>
     <string name="permlab_changeWifiState" msgid="6550641188749128035">"ਵਾਈ-ਫਾਈ ਤੋਂ ਕਨੈਕਟ ਅਤੇ ਡਿਸਕਨੈਕਟ ਕਰੋ"</string>
-    <string name="permdesc_changeWifiState" msgid="7137950297386127533">"ਐਪ ਨੂੰ ਵਾਈ-ਫਾਈ ਐਕਸੈੱਸ ਪੁਆਇੰਟਆਂ ਤੇ ਕਨੈਕਟ ਅਤੇ ਇਹਨਾਂ ਤੋਂ ਡਿਸਕਨੈਕਟ ਕਰਨ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ ਲਈ ਡੀਵਾਈਸ ਸੰਰੂਪਣ ਵਿੱਚ ਬਦਲਾਵ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+    <string name="permdesc_changeWifiState" msgid="7137950297386127533">"ਐਪ ਨੂੰ ਵਾਈ-ਫਾਈ ਪਹੁੰਚ ਬਿੰਦੂਆਂ ਤੇ ਕਨੈਕਟ ਅਤੇ ਇਹਨਾਂ ਤੋਂ ਡਿਸਕਨੈਕਟ ਕਰਨ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈਟਵਰਕਾਂ ਲਈ ਡੀਵਾਈਸ ਸੰਰੂਪਣ ਵਿੱਚ ਬਦਲਾਵ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"ਵਾਈ-ਫਾਈ ਮਲਟੀਕਾਸਟ ਰਿਸੈਪਸ਼ਨ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
     <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"ਐਪ ਨੂੰ ਮਲਟੀਕਾਸਟ ਪਤੇ ਵਰਤਦੇ ਹੋਏ ਇੱਕ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਤੇ ਸਾਰੀਆਂ ਡੀਵਾਈਸਾਂ ਤੇ ਭੇਜੇ ਗਏ ਪੈਕੇਟ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਕੇਵਲ ਤੁਹਾਡਾ ਟੈਬਲੈੱਟ ਨਹੀਂ। ਇਹ ਗੈਰ-ਮਲਟੀਕਾਸਟ ਮੋਡ ਦੇ ਮੁਕਾਬਲੇ ਵੱਧ ਪਾਵਰ ਵਰਤਦਾ ਹੈ।"</string>
     <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"ਐਪ ਨੂੰ ਮਲਟੀਕਾਸਟ ਪਤੇ ਵਰਤਦੇ ਹੋਏ ਇੱਕ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਤੇ ਸਾਰੇ ਡੀਵਾਈਸਾਂ ਤੇ ਭੇਜੇ ਗਏ ਪੈਕੇਟ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਸਿਰਫ਼ ਤੁਹਾਡਾ ਟੀਵੀ ਨਹੀਂ। ਇਹ ਗ਼ੈਰ-ਮਲਟੀਕਾਸਟ ਮੋਡ ਦੇ ਮੁਕਾਬਲੇ ਵੱਧ ਪਾਵਰ ਵਰਤਦਾ ਹੈ।"</string>
-    <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"ਐਪ ਨੂੰ ਮਲਟੀਕਾਸਟ ਪਤੇ, ਵਰਤਦੇ ਹੋਏ ਇੱਕ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਤੇ ਸਾਰੇ ਡੀਵਾਈਸਾਂ ਤੇ ਭੇਜੇ ਗਏ ਪੈਕੇਟ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਸਿਰਫ਼ ਤੁਹਾਡਾ ਫ਼ੋਨ ਨਹੀਂ। ਇਹ ਗ਼ੈਰ-ਮਲਟੀਕਾਸਟ ਮੋਡ ਦੇ ਮੁਕਾਬਲੇ ਵੱਧ ਪਾਵਰ ਵਰਤਦਾ ਹੈ।"</string>
+    <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"ਐਪ ਨੂੰ ਮਲਟੀਕਾਸਟ ਪਤੇ, ਵਰਤਦੇ ਹੋਏ ਇੱਕ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਤੇ ਸਾਰੇ ਡੀਵਾਈਸਾਂ ਤੇ ਭੇਜੇ ਗਏ ਪੈਕੇਟ ਪ੍ਰਾਪਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ, ਸਿਰਫ਼ ਤੁਹਾਡਾ ਫ਼ੋਨ ਨਹੀਂ। ਇਹ ਗੈਰ-ਮਲਟੀਕਾਸਟ ਮੋਡ ਦੇ ਮੁਕਾਬਲੇ ਵੱਧ ਪਾਵਰ ਵਰਤਦਾ ਹੈ।"</string>
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"ਬਲੂਟੁੱਥ ਸੈਟਿੰਗਾਂ ਤੱਕ ਪਹੁੰਚ"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"ਐਪ ਨੂੰ ਸਥਾਨਕ ਬਲੂਟੁੱਥ ਟੈਬਲੈੱਟ ਸੰਰੂਪਣ ਕਰਨ ਅਤੇ ਰਿਮੋਟ ਡੀਵਾਈਸਾਂ ਨੂੰ ਖੋਜਣ ਅਤੇ ਉਹਨਾਂ ਨਾਲ ਜੋੜਾਬੱਧ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permdesc_bluetoothAdmin" product="tv" msgid="3373125682645601429">"ਐਪ ਨੂੰ ਸਥਾਨਕ Bluetooth ਟੀਵੀ ਦੀ ਰੂਪ-ਰੇਖਾ ਬਦਲਣ ਅਤੇ ਰਿਮੋਟ ਡਿਵਾਈਸਾਂ ਨੂੰ ਖੋਜਣ ਅਤੇ ਉਹਨਾਂ ਨਾਲ ਪੇਅਰ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
-    <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"ਐਪ ਨੂੰ ਸਥਾਨਕ Bluetooth ਫ਼ੋਨ ਦੀ ਰੂਪ-ਰੇਖਾ ਬਦਲਣ ਅਤੇ ਰਿਮੋਟ ਡਿਵਾਈਸਾਂ ਨੂੰ ਖੋਜਣ ਅਤੇ ਉਹਨਾਂ ਨਾਲ ਪੇਅਰ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+    <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"ਐਪ ਨੂੰ ਸਥਾਨਕ ਬਲੂਟੁੱਥ ਫ਼ੋਨ ਦੀ ਰੂਪ-ਰੇਖਾ ਬਦਲਣ ਅਤੇ ਰਿਮੋਟ ਡਿਵਾਈਸਾਂ ਨੂੰ ਖੋਜਣ ਅਤੇ ਉਹਨਾਂ ਨਾਲ ਪੇਅਰ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_accessWimaxState" msgid="4195907010610205703">"WiMAX ਤੋਂ ਕਨੈਕਟ ਅਤੇ ਡਿਸਕਨੈਕਟ ਕਰੋ"</string>
     <string name="permdesc_accessWimaxState" msgid="6360102877261978887">"ਐਪ ਨੂੰ ਇਹ ਨਿਰਧਾਰਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ ਕਿ WiMAX ਸਮਰਥਿਤ ਹੈ ਜਾਂ ਨਹੀਂ ਅਤੇ ਕਿਸੇ ਵੀ  WiMAX ਨੈਟਵਰਕਾਂ ਬਾਰੇ ਜਾਣਕਾਰੀ ਜੋ ਕਨੈਕਟ ਕੀਤੇ ਹੋਏ ਹਨ।"</string>
     <string name="permlab_changeWimaxState" msgid="340465839241528618">"WiMAX ਸਥਿਤੀ ਬਦਲੋ"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"ਐਪ ਨੂੰ ਟੈਬਲੈੱਟ ਨੂੰ ਕਨੈਕਟ ਕਰਨ ਅਤੇ WiMAX ਨੈਟਵਰਕਾਂ ਤੋਂ ਟੈਬਲੈੱਟ ਨੂੰ ਡਿਸਕਨੈਕਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permdesc_changeWimaxState" product="tv" msgid="6022307083934827718">"ਐਪ ਨੂੰ TV ਨੂੰ ਕਨੈਕਟ ਕਰਨ ਅਤੇ WiMAX ਨੈਟਵਰਕਾਂ ਤੋਂ TV ਨੂੰ ਡਿਸਕਨੈਕਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
-    <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"ਐਪ ਨੂੰ ਫੋਨ ਨੂੰ ਕਨੈਕਟ ਕਰਨ ਅਤੇ WiMAX ਨੈਟਵਰਕਾਂ ਤੋਂ ਫੋਨ ਨੂੰ ਡਿਸਕਨੈਕਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+    <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"ਐਪ ਨੂੰ ਫ਼ੋਨ ਨੂੰ ਕਨੈਕਟ ਕਰਨ ਅਤੇ WiMAX ਨੈੱਟਵਰਕਾਂ ਤੋਂ ਫ਼ੋਨ ਨੂੰ ਡਿਸਕਨੈਕਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"Bluetooth ਡਿਵਾਈਸਾਂ ਨਾਲ ਪੇਅਰ ਕਰੋ"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"ਐਪ ਨੂੰ ਟੈਬਲੈੱਟ ਤੇ ਬਲੂਟੁੱਥ ਦਾ ਸੰਰੂਪਣ ਦੇਖਣ, ਜੋੜਾਬੱਧ ਕੀਤੇ ਡੀਵਾਈਸਾਂ ਨਾਲ ਕਨੈਕਸ਼ਨ ਬਣਾਉਣ ਅਤੇ ਸਵੀਕਾਰ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
-    <string name="permdesc_bluetooth" product="tv" msgid="3974124940101104206">"ਐਪ ਨੂੰ TV ਤੇ Bluetooth ਦੀ ਕੌਂਫਿਗਰੇਸ਼ਨ ਦੇਖਣ, ਪੇਅਰ ਕੀਤੀਆਂ ਡਿਵਾਈਸਾਂ ਨਾਲ ਕਨੈਕਸ਼ਨ ਬਣਾਉਣ ਅਤੇ ਸਵੀਕਾਰ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
-    <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"ਐਪ ਨੂੰ ਫੋਨ ਤੇ Bluetooth ਦੀ ਕੌਂਫਿਗਰੇਸ਼ਨ ਦੇਖਣ, ਪੇਅਰ ਕੀਤੀਆਂ ਡਿਵਾਈਸਾਂ ਨਾਲ ਕਨੈਕਸ਼ਨ ਬਣਾਉਣ ਅਤੇ ਸਵੀਕਾਰ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+    <string name="permdesc_bluetooth" product="tv" msgid="3974124940101104206">"ਐਪ ਨੂੰ ਟੀਵੀ ਤੇ Bluetooth ਦੀ ਸੰਰੂਪਣ ਦੇਖਣ, ਜੋੜਾਬੱਧ ਕੀਤੇ ਡਿਵਾਈਸਾਂ ਨਾਲ ਕਨੈਕਸ਼ਨ ਬਣਾਉਣ ਅਤੇ ਸਵੀਕਾਰ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+    <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"ਐਪ ਨੂੰ ਬਲੂਟੁੱਥ ਤੇ ਬਲੂਟੁੱਥ ਦਾ ਸੰਰੂਪਣ ਦੇਖਣ, ਜੋੜਾਬੱਧ ਕੀਤੇ ਡੀਵਾਈਸਾਂ ਨਾਲ ਕਨੈਕਸ਼ਨ ਬਣਾਉਣ ਅਤੇ ਸਵੀਕਾਰ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"ਨਜ਼ਦੀਕੀ ਖੇਤਰ ਸੰਚਾਰ ਤੇ ਨਿਯੰਤਰਣ ਪਾਓ"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"ਐਪ ਨੂੰ ਨਜ਼ਦੀਕੀ ਖੇਤਰ ਸੰਚਾਰ (NFC) ਟੈਗਾਂ, ਕਾਰਡਾਂ ਅਤੇ ਰੀਡਰਾਂ ਨਾਲ ਸੰਚਾਰ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"ਆਪਣਾ ਸਕ੍ਰੀਨ ਲੌਕ ਅਸਮਰੱਥ ਬਣਾਓ"</string>
-    <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"ਐਪ ਨੂੰ ਕੀਲਾਕ ਅਤੇ ਕਿਸੇ ਵੀ ਸੰਬੰਧਿਤ ਪਾਸਵਰਡ ਸੁਰੱਖਿਆ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਫ਼ੋਨ ਇੱਕ ਇਨਕਮਿੰਗ ਫ਼ੋਨ ਕਾਲ ਪ੍ਰਾਪਤ ਕਰਨ ਵੇਲੇ ਅਸਮਰੱਥ ਬਣਾਉਂਦਾ ਹੈ, ਫਿਰ ਜਦੋਂ ਕਾਲ ਖਤਮ ਹੁੰਦੀ ਹੈ ਤਾਂ ਕੀਲਾਕ ਨੂੰ ਮੁੜ-ਸਮਰੱਥ ਬਣਾਉਂਦਾ ਹੈ।"</string>
+    <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"ਐਪ ਨੂੰ ਕੀਲਾਕ ਅਤੇ ਕਿਸੇ ਵੀ ਸੰਬੰਧਿਤ ਪਾਸਵਰਡ ਸੁਰੱਖਿਆ ਨੂੰ ਬੰਦ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਫ਼ੋਨ ਇੱਕ ਇਨਕਮਿੰਗ ਫ਼ੋਨ ਕਾਲ ਪ੍ਰਾਪਤ ਕਰਨ ਵੇਲੇ ਬੰਦ ਕਰਦਾ ਹੈ, ਫਿਰ ਜਦੋਂ ਕਾਲ ਖਤਮ ਹੁੰਦੀ ਹੈ ਤਾਂ ਕੀਲਾਕ ਨੂੰ ਮੁੜ-ਚਾਲੂ ਕਰਦਾ ਹੈ।"</string>
     <string name="permlab_manageFingerprint" msgid="5640858826254575638">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਾਰਡਵੇਅਰ ਵਿਵਸਥਿਤ ਕਰੋ"</string>
-    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ਐਪ ਨੂੰ ਵਰਤੋਂ ਲਈ ਫਿੰਗਰਪ੍ਰਿੰਟ ਜੋੜਨ ਅਤੇ ਮਿਟਾਣ ਦੀਆਂ ਵਿਧੀਆਂ ਦੀ ਬੇਨਤੀ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+    <string name="permdesc_manageFingerprint" msgid="178208705828055464">"ਐਪ ਨੂੰ ਵਰਤੋਂ ਲਈ ਫਿੰਗਰਪ੍ਰਿੰਟ ਸ਼ਾਮਲ ਕਰਨ ਅਤੇ ਮਿਟਾਉਣ ਦੀਆਂ ਵਿਧੀਆਂ ਦੀ ਬੇਨਤੀ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਾਰਡਵੇਅਰ ਵਰਤੋ"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ਐਪ ਨੂੰ ਪ੍ਰਮਾਣੀਕਰਨ ਲਈ ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਾਰਡਵੇਅਰ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ਅਧੂਰਾ ਫਿੰਗਰਪ੍ਰਿਟ ਮਿਲਿਆ। ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
@@ -478,14 +478,14 @@
     <string name="fingerprint_name_template" msgid="5870957565512716938">"ਉਂਗਲ <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
   </string-array>
-    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਆਈਕਨ"</string>
+    <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਪ੍ਰਤੀਕ"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ਸਿੰਕ ਸੈਟਿੰਗਾਂ ਪੜ੍ਹੋ"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"ਐਪ ਨੂੰ ਕਿਸੇ ਖਾਤੇ ਲਈ ਸਮਕਾਲੀਕਰਨ ਸੈਟਿੰਗਾਂ ਪੜ੍ਹਨ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਇਹ ਪਤਾ ਕਰ ਸਕਦਾ ਹੈ ਕਿ People ਐਪ ਦਾ ਕਿਸੇ ਖਾਤੇ ਨਾਲ ਸਮਕਾਲੀਕਿਰਤ ਕੀਤਾ ਗਿਆ ਹੈ ਜਾਂ ਨਹੀਂ।"</string>
-    <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ਸਿੰਕ ਟੌਗਲ ਚਾਲੂ ਅਤੇ ਬੰਦ"</string>
+    <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"ਸਮਕਾਲੀਕਰਨ ਚਾਲੂ ਅਤੇ ਬੰਦ ਨੂੰ ਟੌਗਲ ਕਰੋ"</string>
     <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"ਐਪ ਨੂੰ ਇੱਕ ਖਾਤੇ ਲਈ ਸਮਕਾਲੀਕਰਨ ਸੈਟਿੰਗਾਂ ਸੋਧਣ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਇਸਦੀ ਵਰਤੋਂ ਕਿਸੇ ਖਾਤੇ ਨਾਲ People ਐਪ ਦਾ ਸਮਕਾਲੀਕਰਨ ਚਾਲੂ ਕਰਨ ਲਈ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ।"</string>
     <string name="permlab_readSyncStats" msgid="7396577451360202448">"ਸਿੰਕ ਅੰਕੜੇ ਪੜ੍ਹੋ"</string>
     <string name="permdesc_readSyncStats" msgid="1510143761757606156">"ਐਪ ਨੂੰ ਇੱਕ ਖਾਤੇ ਲਈ ਸਮਕਾਲੀਕਰਨ ਸਥਿਤੀ ਪੜ੍ਹਨ ਦੇ ਯੋਗ ਬਣਾਉਂਦਾ ਹੈ, ਇਸ ਵਿੱਚ ਸਮਕਾਲੀਕਰਨ ਵਰਤਾਰਿਆਂ ਦਾ ਇਤਿਹਾਸ ਅਤੇ ਕਿੰਨੇ ਡਾਟਾ ਦਾ ਸਮਕਾਲੀਕਿਰਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ, ਵੀ ਸ਼ਾਮਲ ਹੈ।"</string>
-    <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"ਆਪਣੀ USB ਸਟੋਰੇਜ  ਦੀਆਂ ਸਮੱਗਰੀਆਂ ਪੜ੍ਹੋ"</string>
+    <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"USB ਸਟੋਰੇਜ ਦੀਆਂ ਸਮੱਗਰੀਆਂ ਪੜ੍ਹੋ"</string>
     <string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"ਆਪਣੇ SD ਕਾਰਡ ਦੀਆਂ ਸਮੱਗਰੀਆਂ ਪੜ੍ਹੋ"</string>
     <string name="permdesc_sdcardRead" product="nosdcard" msgid="3446988712598386079">"ਐਪ ਨੂੰ ਆਪਣੀ USB ਸਟੋਰੇਜ ਦੀਆਂ ਸਮੱਗਰੀਆਂ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permdesc_sdcardRead" product="default" msgid="2607362473654975411">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ SD ਕਾਰਡ ਦੀਆਂ ਸਮੱਗਰੀਆਂ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
@@ -518,7 +518,7 @@
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"ਇੱਕ ਸੂਚਨਾ ਸੁਣਨ ਵਾਲੀ ਸੇਵਾ ਨਾਲ ਜੋੜੋ"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"ਹੋਲਡਰ ਨੂੰ ਇੱਕ ਸੂਚਨਾ ਸੁਣਨ ਵਾਲੀ ਸੇਵਾ ਦੇ ਉੱਚ-ਪੱਧਰ ਦੇ ਇੰਟਰਫੇਸ ਨਾਲ ਜੋੜਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਸਧਾਰਨ ਐਪਾਂ ਲਈ ਕਦੇ ਵੀ ਲੋੜੀਂਦਾ ਨਹੀਂ ਹੋਵੇਗਾ।"</string>
     <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"ਇੱਕ ਸਥਿਤੀ ਪ੍ਰਦਾਤਾ ਸੇਵਾ ਨਾਲ ਜੋੜੋ"</string>
-    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"ਹੋਲਡਰ ਨੂੰ ਇੱਕ ਸਥਿਤੀ ਪ੍ਰਦਾਤਾ ਸੇਵਾ ਦੇ ਉੱਚ-ਪੱਧਰ ਦੇ ਇੰਟਰਫੇਸ ਨਾਲ ਜੋੜਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਸਧਾਰਨ ਐਪਾਂ ਲਈ ਕਦੇ ਵੀ ਲੋੜੀਂਦਾ ਨਹੀਂ ਹੋਵੇਗਾ।"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"ਧਾਰਕ ਨੂੰ ਇੱਕ ਸਥਿਤੀ ਪ੍ਰਦਾਤਾ ਸੇਵਾ ਦੇ ਉੱਚ-ਪੱਧਰ ਦੇ ਇੰਟਰਫੇਸ ਨਾਲ ਜੋੜਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਸਧਾਰਨ ਐਪਾਂ ਲਈ ਕਦੇ ਵੀ ਲੋੜੀਂਦਾ ਨਹੀਂ ਹੋਵੇਗਾ।"</string>
     <string name="permlab_bindDreamService" msgid="4153646965978563462">"ਇੱਕ ਡ੍ਰੀਮ ਸੇਵਾ ਨਾਲ ਜੋੜੋ"</string>
     <string name="permdesc_bindDreamService" msgid="7325825272223347863">"ਹੋਲਡਰ ਨੂੰ ਇੱਕ ਡ੍ਰੀਮ ਸੇਵਾ ਦੇ ਉੱਚ-ਪੱਧਰ ਦੇ ਇੰਟਰਫੇਸ ਨਾਲ ਜੋੜਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਸਧਾਰਨ ਐਪਾਂ ਲਈ ਕਦੇ ਵੀ ਲੋੜੀਂਦਾ ਨਹੀਂ ਹੋਵੇਗਾ।"</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"ਕੈਰੀਅਰ-ਵੱਲੋਂ ਮੁਹੱਈਆ ਕੀਤੇ ਕੌਂਫਿਗਰੇਸ਼ਨ ਐਪ ਦੀ ਬੇਨਤੀ ਕਰੋ"</string>
@@ -540,14 +540,14 @@
     <string name="permlab_access_notification_policy" msgid="4247510821662059671">"ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ ਤੱਕ ਪਹੁੰਚ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"ਐਪ ਨੂੰ ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ ਕੌਂਫਿਗਰੇਸ਼ਨ ਨੂੰ ਪੜ੍ਹਨ ਅਤੇ ਲਿਖਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"ਪਾਸਵਰਡ ਨਿਯਮ ਸੈੱਟ ਕਰੋ"</string>
-    <string name="policydesc_limitPassword" msgid="2502021457917874968">"ਸਕ੍ਰੀਨ ਲੌਕ ਪਾਸਵਰਡਾਂ ਅਤੇ ਪਿੰਨ ਵਿੱਚ ਆਗਿਆ ਦਿੱਤੀ ਲੰਮਾਈ ਅਤੇ ਅੱਖਰਾਂ ਤੇ ਨਿਯੰਤਰਣ ਪਾਓ।"</string>
-    <string name="policylab_watchLogin" msgid="5091404125971980158">"ਸਕ੍ਰੀਨ ਅਨਲੌਕ ਕਰਨ ਦੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ \'ਤੇ ਨਿਗਰਾਨੀ ਰੱਖੋ"</string>
+    <string name="policydesc_limitPassword" msgid="2502021457917874968">"ਸਕ੍ਰੀਨ ਲਾਕ ਪਾਸਵਰਡਾਂ ਅਤੇ ਪਿੰਨ ਵਿੱਚ ਆਗਿਆ ਦਿੱਤੀ ਲੰਮਾਈ ਅਤੇ ਅੱਖਰਾਂ ਤੇ ਨਿਯੰਤਰਣ ਪਾਓ।"</string>
+    <string name="policylab_watchLogin" msgid="5091404125971980158">"ਸਕ੍ਰੀਨ ਅਣਲਾਕ ਕਰਨ ਦੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ \'ਤੇ ਨਿਗਰਾਨੀ ਰੱਖੋ"</string>
     <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਹੋਏ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ ਟੈਬਲੈੱਟ ਨੂੰ ਲਾਕ ਕਰੋ ਜਾਂ ਟੈਬਲੈੱਟ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ, ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string>
     <string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਨਲੌਕ ਕਰਦੇ ਸਮੇਂ ਟਾਈਪ ਕੀਤੇ ਗ਼ਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ TV ਨੂੰ ਲੌਕ ਕਰੋ ਜਾਂ TV ਦਾ ਸਾਰਾ  ਡਾਟਾ  ਮਿਟਾਓ ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗ਼ਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string>
-    <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਨਲੌਕ ਕਰਦੇ ਸਮੇਂ ਟਾਈਪ ਕੀਤੇ ਗ਼ਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ ਫੋਨ ਨੂੰ ਲੌਕ ਕਰੋ ਜਾਂ ਫੋਨ ਦਾ ਸਾਰਾ  ਡਾਟਾ  ਮਿਟਾਓ ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗ਼ਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string>
+    <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਸਮੇਂ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ ਫ਼ੋਨ ਨੂੰ ਲਾਕ ਕਰੋ ਜਾਂ ਫ਼ੋਨ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਹੋਏ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ ਟੈਬਲੈੱਟ ਨੂੰ ਲਾਕ ਕਰੋ ਜਾਂ ਟੈਬਲੈੱਟ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ, ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string>
     <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਨਲੌਕ ਕਰਦੇ ਸਮੇਂ ਟਾਈਪ ਕੀਤੇ ਗ਼ਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ TV ਨੂੰ ਲੌਕ ਕਰੋ ਜਾਂ TV ਦਾ ਸਾਰਾ  ਡਾਟਾ  ਮਿਟਾਓ ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗ਼ਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਨਲੌਕ ਕਰਦੇ ਸਮੇਂ ਟਾਈਪ ਕੀਤੇ ਗ਼ਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ ਫੋਨ ਨੂੰ ਲੌਕ ਕਰੋ ਜਾਂ ਫੋਨ ਦਾ ਸਾਰਾ  ਡਾਟਾ  ਮਿਟਾਓ ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗ਼ਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਸਮੇਂ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ ਫ਼ੋਨ ਨੂੰ ਲਾਕ ਕਰੋ ਜਾਂ ਫ਼ੋਨ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string>
     <string name="policylab_resetPassword" msgid="4934707632423915395">"ਸਕ੍ਰੀਨ ਲੌਕ ਬਦਲੋ"</string>
     <string name="policydesc_resetPassword" msgid="1278323891710619128">"ਸਕ੍ਰੀਨ ਲੌਕ ਬਦਲੋ।"</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"ਸਕ੍ਰੀਨ ਲੌਕ ਕਰੋ"</string>
@@ -555,14 +555,14 @@
     <string name="policylab_wipeData" msgid="3910545446758639713">"ਸਾਰਾ  ਡਾਟਾ  ਮਿਟਾਓ"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"ਇੱਕ ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ ਕਰਕੇ ਚਿਤਾਵਨੀ ਤੋਂ ਬਿਨਾਂ ਟੈਬਲੈੱਟ ਦਾ ਡਾਟਾ ਮਿਟਾਓ।"</string>
     <string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"ਇੱਕ ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ ਕਰਕੇ ਚਿਤਾਵਨੀ ਤੋਂ ਬਿਨਾਂ ਟੀਵੀ ਦਾ ਡਾਟਾ ਮਿਟਾਓ।"</string>
-    <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"ਇੱਕ ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ ਕਰਕੇ ਚਿਤਾਵਨੀ ਤੋਂ ਬਿਨਾਂ ਫੋਨ ਦਾ ਡਾਟਾ ਮਿਟਾਓ।"</string>
+    <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"ਇੱਕ ਫੈਕਟਰੀ ਡਾਟਾ ਰੀਸੈੱਟ ਕਰਕੇ ਚਿਤਾਵਨੀ ਤੋਂ ਬਿਨਾਂ ਫ਼ੋਨ ਦਾ ਡਾਟਾ ਮਿਟਾਓ।"</string>
     <string name="policylab_wipeData_secondaryUser" msgid="8362863289455531813">"ਉਪਭੋਗਤਾ  ਡਾਟਾ  ਮਿਟਾਓ"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="6336255514635308054">"ਬਿਨਾਂ ਚਿਤਾਵਨੀ ਦੇ ਇਸ ਟੈਬਲੈੱਟ ਤੇ ਮੌਜੂਦ ਇਸ ਵਰਤੋਂਕਾਰ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ।"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"ਬਿਨਾਂ ਚਿਤਾਵਨੀ ਦੇ ਇਸ TV ਤੇ ਮੌਜੂਦ ਇਸ ਉਪਭੋਗਤਾ ਦਾ ਸਾਰਾ  ਡਾਟਾ  ਮਿਟਾਓ।"</string>
-    <string name="policydesc_wipeData_secondaryUser" product="default" msgid="6787904546711590238">"ਬਿਨਾਂ ਚਿਤਾਵਨੀ ਦੇ ਇਸ ਫੋਨ ਤੇ ਮੌਜੂਦ ਇਸ ਉਪਭੋਗਤਾ ਦਾ ਸਾਰਾ  ਡਾਟਾ  ਮਿਟਾਓ।"</string>
+    <string name="policydesc_wipeData_secondaryUser" product="default" msgid="6787904546711590238">"ਬਿਨਾਂ ਚਿਤਾਵਨੀ ਦੇ ਇਸ ਫ਼ੋਨ ਤੇ ਮੌਜੂਦ ਇਸ ਵਰਤੋਂਕਾਰ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ।"</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"ਡੀਵਾਈਸ ਗਲੋਬਲ ਪ੍ਰੌਕਸੀ ਸੈੱਟ ਕਰੋ"</string>
     <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"ਜਦੋਂ ਨੀਤੀ ਚਾਲੂ ਹੋਵੇ ਤਾਂ ਵਰਤੇ ਜਾਣ ਲਈ ਡੀਵਾਈਸ ਗਲੋਬਲ ਪ੍ਰੌਕਸੀ ਸੈੱਟ ਕਰੋ। ਕੇਵਲ ਡੀਵਾਈਸ ਮਾਲਕ ਗਲੋਬਲ ਪ੍ਰੌਕਸੀ ਸੈੱਟ ਕਰ ਸਕਦਾ ਹੈ।"</string>
-    <string name="policylab_expirePassword" msgid="5610055012328825874">"ਸਕ੍ਰੀਨ ਲੌਕ ਪਾਸਵਰਡ ਸਮਾਪਤੀ ਮਿਆਦ ਸੈੱਟ ਕਰੋ"</string>
+    <string name="policylab_expirePassword" msgid="5610055012328825874">"ਸਕ੍ਰੀਨ ਲਾਕ ਪਾਸਵਰਡ ਸਮਾਪਤੀ ਮਿਆਦ ਸੈੱਟ ਕਰੋ"</string>
     <string name="policydesc_expirePassword" msgid="5367525762204416046">"ਇਸ ਵਿੱਚ ਬਦਲਾਵ ਕਰੋ ਕਿ ਸਕ੍ਰੀਨ ਲਾਕ ਪਾਸਵਰਡ, ਪਿੰਨ ਜਾਂ ਪੈਟਰਨ ਨੂੰ ਕਿੰਨੀ ਵਾਰ ਬਦਲਿਆ ਜਾਣਾ ਚਾਹੀਦਾ ਹੈ।"</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"ਸਟੋਰੇਜ ਇਨਕ੍ਰਿਪਸ਼ਨ ਸੈੱਟ ਕਰੋ"</string>
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"ਲੋੜ ਹੈ ਕਿ ਸਟੋਰ ਕੀਤਾ ਐਪ  ਡਾਟਾ  ਇਨਕ੍ਰਿਪਟ ਕੀਤਾ ਜਾਏ।"</string>
@@ -578,30 +578,30 @@
     <item msgid="1735177144948329370">"ਘਰ ਦੀ ਫੈਕਸ"</item>
     <item msgid="603878674477207394">"ਪੇਜਰ"</item>
     <item msgid="1650824275177931637">"ਹੋਰ"</item>
-    <item msgid="9192514806975898961">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ"</item>
+    <item msgid="9192514806975898961">"ਵਿਉਂਂਤੀ"</item>
   </string-array>
   <string-array name="emailAddressTypes">
     <item msgid="8073994352956129127">"ਘਰ"</item>
     <item msgid="7084237356602625604">"ਕੰਮ"</item>
     <item msgid="1112044410659011023">"ਹੋਰ"</item>
-    <item msgid="2374913952870110618">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ"</item>
+    <item msgid="2374913952870110618">"ਵਿਉਂਂਤੀ"</item>
   </string-array>
   <string-array name="postalAddressTypes">
     <item msgid="6880257626740047286">"ਘਰ"</item>
     <item msgid="5629153956045109251">"ਕੰਮ"</item>
     <item msgid="4966604264500343469">"ਹੋਰ"</item>
-    <item msgid="4932682847595299369">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ"</item>
+    <item msgid="4932682847595299369">"ਵਿਉਂਂਤੀ"</item>
   </string-array>
   <string-array name="imAddressTypes">
     <item msgid="1738585194601476694">"ਘਰ"</item>
     <item msgid="1359644565647383708">"ਕੰਮ"</item>
     <item msgid="7868549401053615677">"ਹੋਰ"</item>
-    <item msgid="3145118944639869809">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ"</item>
+    <item msgid="3145118944639869809">"ਵਿਉਂਂਤੀ"</item>
   </string-array>
   <string-array name="organizationTypes">
     <item msgid="7546335612189115615">"ਕੰਮ"</item>
     <item msgid="4378074129049520373">"ਹੋਰ"</item>
-    <item msgid="3455047468583965104">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ"</item>
+    <item msgid="3455047468583965104">"ਵਿਉਂਂਤੀ"</item>
   </string-array>
   <string-array name="imProtocols">
     <item msgid="8595261363518459565">"AIM"</item>
@@ -613,7 +613,7 @@
     <item msgid="2506857312718630823">"ICQ"</item>
     <item msgid="1648797903785279353">"Jabber"</item>
   </string-array>
-    <string name="phoneTypeCustom" msgid="1644738059053355820">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ"</string>
+    <string name="phoneTypeCustom" msgid="1644738059053355820">"ਵਿਉਂਂਤੀ"</string>
     <string name="phoneTypeHome" msgid="2570923463033985887">"ਘਰ"</string>
     <string name="phoneTypeMobile" msgid="6501463557754751037">"ਮੋਬਾਈਲ"</string>
     <string name="phoneTypeWork" msgid="8863939667059911633">"ਕੰਮ"</string>
@@ -634,24 +634,24 @@
     <string name="phoneTypeWorkPager" msgid="649938731231157056">"ਦਫ਼ਤਰ ਦਾ ਪੇਜਰ"</string>
     <string name="phoneTypeAssistant" msgid="5596772636128562884">"ਸਹਾਇਕ"</string>
     <string name="phoneTypeMms" msgid="7254492275502768992">"MMS"</string>
-    <string name="eventTypeCustom" msgid="7837586198458073404">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ"</string>
+    <string name="eventTypeCustom" msgid="7837586198458073404">"ਵਿਉਂਂਤੀ"</string>
     <string name="eventTypeBirthday" msgid="2813379844211390740">"ਜਨਮਦਿਨ"</string>
     <string name="eventTypeAnniversary" msgid="3876779744518284000">"ਵਰ੍ਹੇਗੰਢ"</string>
     <string name="eventTypeOther" msgid="7388178939010143077">"ਹੋਰ"</string>
-    <string name="emailTypeCustom" msgid="8525960257804213846">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ"</string>
+    <string name="emailTypeCustom" msgid="8525960257804213846">"ਵਿਉਂਂਤੀ"</string>
     <string name="emailTypeHome" msgid="449227236140433919">"ਘਰ"</string>
     <string name="emailTypeWork" msgid="3548058059601149973">"ਕੰਮ"</string>
     <string name="emailTypeOther" msgid="2923008695272639549">"ਹੋਰ"</string>
     <string name="emailTypeMobile" msgid="119919005321166205">"ਮੋਬਾਈਲ"</string>
-    <string name="postalTypeCustom" msgid="8903206903060479902">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ"</string>
+    <string name="postalTypeCustom" msgid="8903206903060479902">"ਵਿਉਂਂਤੀ"</string>
     <string name="postalTypeHome" msgid="8165756977184483097">"ਘਰ"</string>
     <string name="postalTypeWork" msgid="5268172772387694495">"ਕੰਮ"</string>
     <string name="postalTypeOther" msgid="2726111966623584341">"ਹੋਰ"</string>
-    <string name="imTypeCustom" msgid="2074028755527826046">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ"</string>
+    <string name="imTypeCustom" msgid="2074028755527826046">"ਵਿਉਂਂਤੀ"</string>
     <string name="imTypeHome" msgid="6241181032954263892">"ਘਰ"</string>
     <string name="imTypeWork" msgid="1371489290242433090">"ਕੰਮ"</string>
     <string name="imTypeOther" msgid="5377007495735915478">"ਹੋਰ"</string>
-    <string name="imProtocolCustom" msgid="6919453836618749992">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ"</string>
+    <string name="imProtocolCustom" msgid="6919453836618749992">"ਵਿਉਂਂਤੀ"</string>
     <string name="imProtocolAim" msgid="7050360612368383417">"AIM"</string>
     <string name="imProtocolMsn" msgid="144556545420769442">"Windows Live"</string>
     <string name="imProtocolYahoo" msgid="8271439408469021273">"Yahoo"</string>
@@ -663,8 +663,8 @@
     <string name="imProtocolNetMeeting" msgid="8287625655986827971">"NetMeeting"</string>
     <string name="orgTypeWork" msgid="29268870505363872">"ਕੰਮ"</string>
     <string name="orgTypeOther" msgid="3951781131570124082">"ਹੋਰ"</string>
-    <string name="orgTypeCustom" msgid="225523415372088322">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ"</string>
-    <string name="relationTypeCustom" msgid="3542403679827297300">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ"</string>
+    <string name="orgTypeCustom" msgid="225523415372088322">"ਵਿਉਂਂਤੀ"</string>
+    <string name="relationTypeCustom" msgid="3542403679827297300">"ਵਿਉਂਂਤੀ"</string>
     <string name="relationTypeAssistant" msgid="6274334825195379076">"ਸਹਾਇਕ"</string>
     <string name="relationTypeBrother" msgid="8757913506784067713">"ਭਰਾ"</string>
     <string name="relationTypeChild" msgid="1890746277276881626">"ਬੱਚਾ"</string>
@@ -679,7 +679,7 @@
     <string name="relationTypeRelative" msgid="1799819930085610271">"ਰਿਸ਼ਤੇਦਾਰ"</string>
     <string name="relationTypeSister" msgid="1735983554479076481">"ਭੈਣ"</string>
     <string name="relationTypeSpouse" msgid="394136939428698117">"ਜੀਵਨਸਾਥੀ"</string>
-    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ"</string>
+    <string name="sipAddressTypeCustom" msgid="2473580593111590945">"ਵਿਉਂਂਤੀ"</string>
     <string name="sipAddressTypeHome" msgid="6093598181069359295">"ਘਰ"</string>
     <string name="sipAddressTypeWork" msgid="6920725730797099047">"ਕੰਮ"</string>
     <string name="sipAddressTypeOther" msgid="4408436162950119849">"ਹੋਰ"</string>
@@ -689,50 +689,50 @@
     <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK ਕੋਡ"</string>
     <string name="keyguard_password_enter_pin_prompt" msgid="8027680321614196258">"ਨਵਾਂ ਪਿੰਨ ਕੋਡ"</string>
     <string name="keyguard_password_entry_touch_hint" msgid="2644215452200037944"><font size="17">"ਪਾਸਵਰਡ ਟਾਈਪ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"ਅਨਲੌਕ ਕਰਨ ਲਈ ਪਾਸਵਰਡ ਟਾਈਪ ਕਰੋ"</string>
+    <string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"ਅਣਲਾਕ ਕਰਨ ਲਈ ਪਾਸਵਰਡ ਟਾਈਪ ਕਰੋ"</string>
     <string name="keyguard_password_enter_pin_password_code" msgid="6391755146112503443">"ਅਣਲਾਕ ਕਰਨ ਲਈ ਪਿੰਨ ਟਾਈਪ ਕਰੋ"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"ਗਲਤ ਪਿੰਨ ਕੋਡ।"</string>
-    <string name="keyguard_label_text" msgid="861796461028298424">"ਅਨਲੌਕ ਕਰਨ ਲਈ, ਪਹਿਲਾਂ ਮੀਨੂ ਫਿਰ 0 ਦਬਾਓ।"</string>
+    <string name="keyguard_label_text" msgid="861796461028298424">"ਅਣਲਾਕ ਕਰਨ ਲਈ, ਪਹਿਲਾਂ ਮੀਨੂ ਫਿਰ 0 ਦਬਾਓ।"</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"ਐਮਰਜੈਂਸੀ ਨੰਬਰ"</string>
     <string name="lockscreen_carrier_default" msgid="6169005837238288522">"ਕੋਈ ਸੇਵਾ ਨਹੀਂ"</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_disabled" msgid="686260028797158364">"ਅਨਲੌਕ ਕਰਨ ਲਈ ਮੀਨੂ ਦਬਾਓ।"</string>
-    <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"ਅਨਲੌਕ ਕਰਨ ਲਈ ਪੈਟਰਨ ਡ੍ਰਾ ਕਰੋ"</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="5298642613417801888">"ਸੰਕਟਕਾਲ"</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>
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
-    <string name="lockscreen_storage_locked" msgid="9167551160010625200">"ਸਾਰੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਅਤੇ ਡੈਟੇ ਲਈ ਅਨਲੌਕ ਕਰੋ"</string>
-    <string name="faceunlock_multiple_failures" msgid="754137583022792429">"ਅਧਿਕਤਮ ਚਿਹਰਾ ਅਨਲੌਕ ਕੋਸ਼ਿਸ਼ਾਂ ਵਧੀਆਂ"</string>
+    <string name="lockscreen_storage_locked" msgid="9167551160010625200">"ਸਾਰੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਅਤੇ ਡਾਟੇ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string>
+    <string name="faceunlock_multiple_failures" msgid="754137583022792429">"ਅਧਿਕਤਮ ਚਿਹਰਾ ਅਣਲਾਕ ਕੋਸ਼ਿਸ਼ਾਂ ਵਧੀਆਂ"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"ਕੋਈ ਸਿਮ ਕਾਰਡ ਨਹੀਂ"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ਟੈਬਲੈੱਟ ਵਿੱਚ ਕੋਈ ਸਿਮ ਕਾਰਡ ਨਹੀਂ ਹੈ।"</string>
     <string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"TV ਵਿੱਚ ਕੋਈ ਸਿਮ ਕਾਰਡ ਨਹੀਂ।"</string>
-    <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ਫੋਨ ਵਿੱਚ ਕੋਈ ਸਿਮ ਕਾਰਡ ਨਹੀਂ।"</string>
+    <string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"ਫ਼ੋਨ ਵਿੱਚ ਕੋਈ ਸਿਮ ਕਾਰਡ ਮੌਜੂਦ ਨਹੀਂ।"</string>
     <string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"ਇੱਕ SIM ਕਾਰਡ ਪਾਓ।"</string>
     <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"SIM ਕਾਰਡ ਲੁਪਤ ਹੈ ਜਾਂ ਪੜ੍ਹਨਯੋਗ ਨਹੀਂ ਹੈ। ਇੱਕ SIM ਕਾਰਡ ਪਾਓ।"</string>
     <string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"ਨਾਵਰਤਣਯੋਗ SIM ਕਾਰਡ।"</string>
-    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"ਤੁਹਾਡਾ SIM ਕਾਰਡ ਸਥਾਈ ਤੌਰ ਤੇ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ।\n ਦੂਜੇ SIM ਕਾਰਡ ਲਈ ਆਪਣੇ ਵਾਇਰਲੈਸ ਸੇਵਾ ਪ੍ਰਦਾਤਾ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
+    <string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"ਤੁਹਾਡਾ ਸਿਮ ਕਾਰਡ ਸਥਾਈ ਤੌਰ \'ਤੇ ਅਯੋਗ ਬਣਾ ਦਿੱਤਾ ਗਿਆ ਹੈ।\n ਇੱਕ ਹੋਰ ਸਿਮ ਕਾਰਡ ਲਈ ਆਪਣੇ ਵਾਇਰਲੈੱਸ ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
     <string name="lockscreen_transport_prev_description" msgid="6300840251218161534">"ਪਿਛਲਾ ਟਰੈਕ"</string>
     <string name="lockscreen_transport_next_description" msgid="573285210424377338">"ਅਗਲਾ ਟਰੈਕ"</string>
     <string name="lockscreen_transport_pause_description" msgid="3980308465056173363">"ਰੋਕੋ"</string>
     <string name="lockscreen_transport_play_description" msgid="1901258823643886401">"ਪਲੇ ਕਰੋ"</string>
     <string name="lockscreen_transport_stop_description" msgid="5907083260651210034">"ਰੋਕੋ"</string>
     <string name="lockscreen_transport_rew_description" msgid="6944412838651990410">"ਰੀਵਾਈਂਡ ਕਰੋ"</string>
-    <string name="lockscreen_transport_ffw_description" msgid="42987149870928985">"ਅੱਗੇ ਭੇਜੋ"</string>
+    <string name="lockscreen_transport_ffw_description" msgid="42987149870928985">"ਤੇਜ਼ੀ ਨਾਲ ਅੱਗੇ ਭੇਜੋ"</string>
     <string name="emergency_calls_only" msgid="6733978304386365407">"ਕੇਵਲ ਐਮਰਜੈਂਸੀ ਕਾਲਾਂ"</string>
     <string name="lockscreen_network_locked_message" msgid="143389224986028501">"ਨੈੱਟਵਰਕ ਲੌਕ ਕੀਤਾ"</string>
     <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM ਕਾਰਡ PUK-ਲੌਕਡ ਹੈ।"</string>
-    <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"ਉਪਭੋਗਤਾ ਗਾਈਡ ਦੇਖੋ ਜਾਂ ਗਾਹਕ ਸੇਵਾ ਨੂੰ ਫੋਨ ਕਰੋ।"</string>
+    <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"ਵਰਤੋਂਕਾਰ ਗਾਈਡ ਦੇਖੋ ਜਾਂ ਗਾਹਕ ਸੇਵਾ ਨੂੰ ਫ਼ੋਨ ਕਰੋ।"</string>
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM ਕਾਰਡ ਲੌਕ ਕੀਤਾ ਹੋਇਆ ਹੈ।"</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"SIM ਕਾਰਡ ਅਨਲੌਕ ਕਰ ਰਿਹਾ ਹੈ…"</string>
-    <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਨਲੌਕ ਪੈਟਰਨ ਗ਼ਲਤ ਢੰਗ ਨਾਲ ਡ੍ਰਾ ਕੀਤਾ ਹੈ। \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
-    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਪਾਸਵਰਡ ਗ਼ਲਤ ਢੰਗ ਨਾਲ ਟਾਈਪ ਕੀਤਾ ਹੈ। \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ ਹੈ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਪਾਸਵਰਡ ਗਲਤ ਢੰਗ ਨਾਲ ਟਾਈਪ ਕੀਤਾ ਹੈ।\n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"ਤੁਸੀਂ ਆਪਣਾ ਪਿੰਨ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟਾਈਪ ਕੀਤਾ ਹੈ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਆਪਣਾ Google ਸਾਈਨ-ਇਨ ਵਰਤਦੇ ਹੋਏ ਆਪਣਾ ਟੈਬਲੈੱਟ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਵੇਗਾ। \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਨਲੌਕ ਪੈਟਰਨ ਗ਼ਲਤ ਢੰਗ ਨਾਲ ਡ੍ਰਾ ਕੀਤਾ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਆਪਣਾ Google ਸਾਈਨਇਨ ਵਰਤਦੇ ਹੋਏ ਆਪਣਾ TV ਅਨਲੌਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਏਗਾ।\n\n  <xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਨਲੌਕ ਪੈਟਰਨ ਗ਼ਲਤ ਢੰਗ ਨਾਲ ਡ੍ਰਾ ਕੀਤਾ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਆਪਣਾ Google ਸਾਈਨਇਨ ਵਰਤਦੇ ਹੋਏ ਆਪਣਾ ਫੋਨ ਅਨਲੌਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਏਗਾ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਡ੍ਰਾ ਕੀਤਾ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਆਪਣਾ Google ਸਾਈਨ-ਇਨ ਵਰਤਦੇ ਹੋਏ ਆਪਣੀ ਟੈਬਲੈੱਟ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਏਗਾ। \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਡ੍ਰਾ ਕੀਤਾ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਆਪਣਾ Google ਸਾਈਨ-ਇਨ ਵਰਤਦੇ ਹੋਏ ਆਪਣਾ ਟੀਵੀ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਏਗਾ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਡ੍ਰਾ ਕੀਤਾ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਆਪਣਾ Google ਸਾਈਨਇਨ ਵਰਤਦੇ ਹੋਏ ਆਪਣਾ ਫ਼ੋਨ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਏਗਾ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਵੱਧ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਟੈਬਲੈੱਟ ਫੈਕਟਰੀ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਤੇ ਰੀਸੈੱਟ ਹੋ ਜਾਵੇਗਾ ਅਤੇ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡਾਟਾ ਨਸ਼ਟ ਹੋ ਜਾਵੇਗਾ।"</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="950408382418270260">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੀਵੀ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਵੱਧ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਟੀਵੀ ਫੈਕਟਰੀ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਤੇ ਰੀਸੈੱਟ ਹੋ ਜਾਏਗਾ ਅਤੇ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡਾਟਾ ਨਸ਼ਟ ਹੋ ਜਾਏਗਾ।"</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਵੱਧ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਫ਼ੋਨ ਫੈਕਟਰੀ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਤੇ ਰੀਸੈੱਟ ਹੋ ਜਾਏਗਾ ਅਤੇ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡਾਟਾ ਨਸ਼ਟ ਹੋ ਜਾਏਗਾ।"</string>
@@ -747,10 +747,10 @@
     <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"ਵਰਤੋਂਕਾਰ ਨਾਮ (ਈਮੇਲ)"</string>
     <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"ਪਾਸਵਰਡ"</string>
     <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"ਸਾਈਨ-ਇਨ ਕਰੋ"</string>
-    <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"ਅਪ੍ਰਮਾਣਿਕ ਵਰਤੋਂਕਾਰ ਨਾਮ ਜਾਂ ਪਾਸਵਰਡ।"</string>
+    <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"ਅਵੈਧ ਵਰਤੋਂਕਾਰ ਨਾਮ ਜਾਂ ਪਾਸਵਰਡ।"</string>
     <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"ਕੀ ਤੁਸੀਂ ਆਪਣਾ ਵਰਤੋਂਕਾਰ ਨਾਮ ਜਾਂ ਪਾਸਵਰਡ ਭੁੱਲ ਗਏ ਹੋ?\n"<b>"google.com/accounts/recovery"</b>" ਤੇ ਜਾਓ।"</string>
     <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"ਜਾਂਚ ਕਰ ਰਿਹਾ ਹੈ..."</string>
-    <string name="lockscreen_unlock_label" msgid="737440483220667054">"ਅਨਲੌਕ ਕਰੋ"</string>
+    <string name="lockscreen_unlock_label" msgid="737440483220667054">"ਅਣਲਾਕ ਕਰੋ"</string>
     <string name="lockscreen_sound_on_label" msgid="9068877576513425970">"ਅਵਾਜ਼ ਚਾਲੂ"</string>
     <string name="lockscreen_sound_off_label" msgid="996822825154319026">"ਅਵਾਜ਼ ਬੰਦ"</string>
     <string name="lockscreen_access_pattern_start" msgid="3941045502933142847">"ਪੈਟਰਨ ਚਾਲੂ ਕੀਤਾ"</string>
@@ -760,10 +760,10 @@
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"ਪੈਟਰਨ ਪੂਰਾ ਕੀਤਾ"</string>
     <string name="lockscreen_access_pattern_area" msgid="400813207572953209">"ਪੈਟਰਨ ਖੇਤਰ।"</string>
     <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s। %3$d ਦਾ ਵਿਜੇਟ %2$d।"</string>
-    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"ਵਿਜੇਟ ਜੋੜੋ।"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"ਵਿਜੇਟ ਸ਼ਾਮਲ ਕਰੋ।"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"ਖਾਲੀ"</string>
-    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"ਅਨਲੌਕ ਖੇਤਰ ਦਾ ਵਿਸਤਾਰ ਕੀਤਾ।"</string>
-    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"ਅਨਲੌਕ ਖੇਤਰ ਨਸ਼ਟ ਕੀਤਾ।"</string>
+    <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"ਅਣਲਾਕ ਖੇਤਰ ਦਾ ਵਿਸਤਾਰ ਕੀਤਾ।"</string>
+    <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"ਅਣਲਾਕ ਖੇਤਰ ਨਸ਼ਟ ਕੀਤਾ।"</string>
     <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> ਵਿਜੇਟ।"</string>
     <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"ਉਪਭੋਗਤਾ ਚੋਣਕਾਰ"</string>
     <string name="keyguard_accessibility_status" msgid="8008264603935930611">"ਅਵਸਥਾ"</string>
@@ -772,12 +772,12 @@
     <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"ਵਿਜੇਟ ਨੂੰ ਪੁਨਰ ਤਰਤੀਬ ਦੇਣਾ ਸ਼ੁਰੂ ਹੋਇਆ।"</string>
     <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"ਵਿਜੇਟ ਨੂੰ ਪੁਨਰ ਤਰਤੀਬ ਦੇਣਾ ਖ਼ਤਮ ਹੋਇਆ।"</string>
     <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"ਵਿਜੇਟ <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> ਮਿਟਾਇਆ।"</string>
-    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"ਅਨਲੌਕ ਖੇਤਰ ਦਾ ਵਿਸਤਾਰ ਕਰੋ।"</string>
-    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"ਅਨਲੌਕ ਸਲਾਈਡ ਕਰੋ।"</string>
-    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ਪੈਟਰਨ ਅਨਲੌਕ।"</string>
-    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"ਚਿਹਰਾ ਅਨਲੌਕ।"</string>
+    <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"ਅਣਲਾਕ ਖੇਤਰ ਦਾ ਵਿਸਤਾਰ ਕਰੋ।"</string>
+    <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"ਅਣਲਾਕ ਸਲਾਈਡ ਕਰੋ।"</string>
+    <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ਪੈਟਰਨ ਅਣਲਾਕ।"</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"ਚਿਹਰਾ ਅਣਲਾਕ।"</string>
     <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"ਪਿੰਨ ਅਣਲਾਕ।"</string>
-    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"ਪਾਸਵਰਡ ਅਨਲੌਕ।"</string>
+    <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"ਪਾਸਵਰਡ ਅਣਲਾਕ।"</string>
     <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ਪੈਟਰਨ ਖੇਤਰ।"</string>
     <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ਖੇਤਰ ਸਲਾਈਡ ਕਰੋ।"</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
@@ -788,15 +788,15 @@
     <string name="granularity_label_link" msgid="5815508880782488267">"ਲਿੰਕ"</string>
     <string name="granularity_label_line" msgid="5764267235026120888">"ਲਾਈਨ"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"ਫੈਕਟਰੀ ਜਾਂਚ ਅਸਫਲ"</string>
-    <string name="factorytest_not_system" msgid="4435201656767276723">"FACTORY_TEST ਕਿਰਿਆ ਕੇਵਲ /ਸਿਸਟਮ/ਐਪ ਵਿੱਚ ਇੰਸਟੌਲ ਕੀਤੇ ਪੈਕੇਜਾਂ ਲਈ ਸਮਰਥਿਤ ਹੈ।"</string>
-    <string name="factorytest_no_action" msgid="872991874799998561">"ਅਜਿਹਾ ਕੋਈ ਪੈਕੇਜ ਨਹੀਂ ਮਿਲਿਆ ਜੋ FACTORY_TEST ਕਿਰਿਆ ਮੁਹੱਈਆ ਕਰਦਾ ਹੈ।"</string>
+    <string name="factorytest_not_system" msgid="4435201656767276723">"FACTORY_TEST ਕਾਰਵਾਈ ਕੇਵਲ /ਸਿਸਟਮ/ਐਪ ਵਿੱਚ ਸਥਾਪਤ ਕੀਤੇ ਪੈਕੇਜਾਂ ਲਈ ਸਮਰਥਿਤ ਹੈ।"</string>
+    <string name="factorytest_no_action" msgid="872991874799998561">"ਅਜਿਹਾ ਕੋਈ ਪੈਕੇਜ ਨਹੀਂ ਮਿਲਿਆ ਜੋ FACTORY_TEST ਕਾਰਵਾਈ ਮੁਹੱਈਆ ਕਰਦਾ ਹੈ।"</string>
     <string name="factorytest_reboot" msgid="6320168203050791643">"ਰੀਬੂਟ ਕਰੋ"</string>
     <string name="js_dialog_title" msgid="1987483977834603872">"\"<xliff:g id="TITLE">%s</xliff:g>\" ਤੇ ਸਫ਼ੇ ਦੇ ਮੁਤਾਬਕ:"</string>
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload_title" msgid="2619376555525116593">"ਨੈਵੀਗੇਸ਼ਨ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ"</string>
     <string name="js_dialog_before_unload_positive_button" msgid="3112752010600484130">"ਇਹ ਸਫ਼ਾ ਛੱਡੋ"</string>
     <string name="js_dialog_before_unload_negative_button" msgid="5614861293026099715">"ਇਸ ਸ਼ਫ਼ੇ ਤੇ ਰਹੋ"</string>
-    <string name="js_dialog_before_unload" msgid="3468816357095378590">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nਕੀ ਤੁਸੀਂ ਯਕੀਨੀ ਤੌਰ ਤੇ ਇਸ ਪੇਜ ਤੋਂ ਦੂਰ ਨੈਵੀਗੇਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
+    <string name="js_dialog_before_unload" msgid="3468816357095378590">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nਕੀ ਤੁਸੀਂ ਯਕੀਨੀ ਤੌਰ ਤੇ ਇਸ ਪੇਜ ਤੋਂ ਦੂਰ ਜਾਣਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
     <string name="save_password_label" msgid="6860261758665825069">"ਪੁਸ਼ਟੀ ਕਰੋ"</string>
     <string name="double_tap_toast" msgid="4595046515400268881">"ਨੁਕਤਾ: ਜ਼ੂਮ ਵਧਾਉਣ ਅਤੇ ਘਟਾਉਣ ਲਈ ਡਬਲ ਟੈਪ ਕਰੋ।"</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"ਆਟੋਫਿਲ"</string>
@@ -825,8 +825,8 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"ਐਪ ਨੂੰ ਬ੍ਰਾਊਜ਼ਰ ਦਾ ਇਤਿਹਾਸ ਅਤੇ ਤੁਹਾਡੇ ਫ਼ੋਨ ਤੇ ਸਟੋਰ ਕੀਤੇ ਬੁੱਕਮਾਰਕਾਂ ਨੂੰ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਐਪ ਨੂੰ ਬ੍ਰਾਊਜ਼ਰ ਡਾਟਾ ਮਿਟਾਉਣ ਜਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇ ਸਕਦਾ ਹੈ। ਨੋਟ: ਇਹ ਅਨੁਮਤੀ ਤੀਜੀ-ਪਾਰਟੀ ਬ੍ਰਾਊਜ਼ਰਾਂ ਜਾਂ ਵੈੱਬ ਬ੍ਰਾਊਜ਼ਿੰਗ ਸਮਰੱਥਤਾਵਂ ਵਾਲੀਆਂ ਹੋਰਾਂ ਐਪਲੀਕੇਸ਼ਨਾਂ ਵੱਲੋਂ ਲਾਗੂ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ।"</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"ਇੱਕ ਅਲਾਰਮ ਸੈੱਟ ਕਰੋ"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"ਐਪ ਨੂੰ ਇੱਕ ਇੰਸਟੌਲ ਕੀਤੀ ਅਲਾਰਮ ਘੜੀ ਐਪ ਵਿੱਚ ਇੱਕ ਅਲਾਰਮ ਸੈਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਕੁਝ ਅਲਾਰਮ ਘੜੀ ਐਪਲ ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਲਾਗੂ ਨਹੀਂ ਵੀ ਕਰ ਸਕਦੇ।"</string>
-    <string name="permlab_addVoicemail" msgid="5525660026090959044">"ਵੌਇਸਮੇਲ ਜੋੜੋ"</string>
-    <string name="permdesc_addVoicemail" msgid="6604508651428252437">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਵੌਇਸਮੇਲ ਇਨਬੌਕਸ ਵਿੱਚ ਸੁਨੇਹੇ ਜੋੜਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+    <string name="permlab_addVoicemail" msgid="5525660026090959044">"ਵੌਇਸਮੇਲ ਸ਼ਾਮਲ ਕਰੋ"</string>
+    <string name="permdesc_addVoicemail" msgid="6604508651428252437">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਵੌਇਸਮੇਲ ਇਨਬਾਕਸ ਵਿੱਚ ਸੁਨੇਹੇ ਸ਼ਾਮਲ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ਬ੍ਰਾਊਜ਼ਰ ਜਿਓਲੋਕੇਸ਼ਨ ਇਜਾਜ਼ਤਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰੋ"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"ਐਪ ਨੂੰ ਬ੍ਰਾਊਜ਼ਰ ਦੀਆਂ ਜਿਓਲੋਕੇਸ਼ਨ ਅਨੁਮਤੀਆਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਖਰਾਬ ਐਪਾਂ ਇਸਦੀ ਵਰਤੋਂ ਆਰਬਿਟਰੇਰੀ ਵੈੱਬ ਸਾਈਟਾਂ ਨੂੰ ਟਿਕਾਣਾ ਜਾਣਕਾਰੀ ਭੇਜਣ ਦੀ ਆਗਿਆ ਦੇਣ ਲਈ ਕਰ ਸਕਦੇ ਹਨ।"</string>
     <string name="save_password_message" msgid="767344687139195790">"ਕੀ ਤੁਸੀਂ ਚਾਹੁੰਦੇ ਹੋ ਕਿ ਬ੍ਰਾਊਜ਼ਰ ਇਹ ਪਾਸਵਰਡ ਯਾਦ ਰੱਖੇ?"</string>
@@ -843,13 +843,13 @@
     <string name="search_go" msgid="8298016669822141719">"ਖੋਜੋ"</string>
     <string name="search_hint" msgid="1733947260773056054">"ਖੋਜ…"</string>
     <string name="searchview_description_search" msgid="6749826639098512120">"ਖੋਜੋ"</string>
-    <string name="searchview_description_query" msgid="5911778593125355124">"ਸਵਾਲ ਖੋਜੋ"</string>
+    <string name="searchview_description_query" msgid="5911778593125355124">"ਖੋਜ ਪੁੱਛਗਿੱਛ"</string>
     <string name="searchview_description_clear" msgid="1330281990951833033">"ਸਵਾਲ ਹਟਾਓ"</string>
     <string name="searchview_description_submit" msgid="2688450133297983542">"ਸਵਾਲ ਪ੍ਰਸਤੁਤ ਕਰੋ"</string>
     <string name="searchview_description_voice" msgid="2453203695674994440">"ਵੌਇਸ ਖੋਜ"</string>
     <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"ਕੀ ਸਪੱਰਸ਼ ਰਾਹੀਂ ਪੜਚੋਲ ਕਰੋ ਨੂੰ ਚਾਲੂ ਕਰਨਾ ਹੈ?"</string>
     <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> \'ਸਪੱਰਸ਼ ਰਾਹੀਂ ਪੜਚੋਲ\' ਨੂੰ ਸਮਰੱਥ ਬਣਾਉਣਾ ਚਾਹੁੰਦੀ ਹੈ। ਜਦੋਂ \'ਸਪੱਰਸ਼ ਰਾਹੀਂ ਪੜਚੋਲ\' ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ, ਤਾਂ ਤੁਸੀਂ ਇਸ ਬਾਰੇ ਵੇਰਵੇ ਸੁਣ ਜਾਂ ਦੇਖ ਸਕਦੇ ਹੋ ਕਿ ਤੁਹਾਡੀ ਉਂਗਲੀ ਦੇ ਹੇਠਾਂ ਕੀ ਹੈ ਜਾਂ ਟੈਬਲੈੱਟ ਨਾਲ ਇੰਟਰੈਕਟ ਕਰਨ ਲਈ ਸੰਕੇਤਾਂ ਦੀ ਪਾਲਣਾ ਕਰ ਸਕਦੇ ਹੋ।"</string>
-    <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ਸਪੱਰਸ਼ ਰਾਹੀਂ ਪੜਚੋਲ ਕਰੋ ਨੂੰ ਚਾਲੂ ਕਰਨਾ ਚਾਹੁੰਦਾ ਹੈ। ਜਦੋਂ ਸਪੱਰਸ਼ ਰਾਹੀਂ ਪੜਚੋਲ ਕਰੋ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ, ਤਾਂ ਤੁਸੀਂ ਇਸ ਬਾਰੇ ਵੇਰਵੇ ਸੁਣ ਜਾਂ ਦੇਖ ਸਕਦੇ ਹੋ ਤਿ ਤੁਹਾਡੀ ਉਂਗਲੀ ਦੇ ਹੇਠਾਂ ਕੀ ਹੈ ਜਾਂ ਫ਼ੋਨ ਨਾਲ ਇੰਟਰੈਕਟ ਕਰਨ ਲਈ ਸੰਕੇਤ ਪਰਫੌਰਮ ਕਰ ਸਕਦੇ ਹੋ।"</string>
+    <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> ਸਪਰਸ਼ ਰਾਹੀਂ ਪੜਚੋਲ ਕਰੋ ਨੂੰ ਚਾਲੂ ਕਰਨਾ ਚਾਹੁੰਦਾ ਹੈ। ਜਦੋਂ ਸਪਰਸ਼ ਰਾਹੀਂ ਪੜਚੋਲ ਕਰੋ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ, ਤਾਂ ਤੁਸੀਂ ਇਸ ਬਾਰੇ ਵੇਰਵੇ ਸੁਣ ਜਾਂ ਦੇਖ ਸਕਦੇ ਹੋ ਤਿ ਤੁਹਾਡੀ ਉਂਗਲੀ ਦੇ ਹੇਠਾਂ ਕੀ ਹੈ ਜਾਂ ਫ਼ੋਨ ਨਾਲ ਇੰਟਰੈਕਟ ਕਰਨ ਲਈ ਸੰਕੇਤ ਪਰਫੌਰਮ ਕਰ ਸਕਦੇ ਹੋ।"</string>
     <string name="oneMonthDurationPast" msgid="7396384508953779925">"1 ਮਹੀਨੇ ਪਹਿਲਾਂ"</string>
     <string name="beforeOneMonthDurationPast" msgid="909134546836499826">"1 ਮਹੀਨਾ ਪਹਿਲਾਂ ਤੋਂ ਪਹਿਲਾਂ"</string>
     <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
@@ -939,7 +939,7 @@
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ਸਾਲ ਵਿੱਚ</item>
     </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"ਵੀਡੀਓ ਸਮੱਸਿਆ"</string>
-    <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"ਇਹ ਵੀਡੀਓ ਇਸ ਡੀਵਾਈਸ ਤੇ ਸਟ੍ਰੀਮਿੰਗ ਲਈ ਵੈਧ ਨਹੀਂ ਹੈ।"</string>
+    <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"ਇਹ ਵੀਡੀਓ ਇਸ ਡੀਵਾਈਸ ਤੇ ਸਟ੍ਰੀਮਿੰਗ ਲਈ ਪ੍ਰਮਾਣਕ ਨਹੀਂ ਹੈ।"</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"ਇਹ ਵੀਡੀਓ ਪਲੇ ਨਹੀਂ ਕਰ ਸਕਦੇ।"</string>
     <string name="VideoView_error_button" msgid="2822238215100679592">"ਠੀਕ"</string>
     <string name="relative_time" msgid="1818557177829411417">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -953,7 +953,7 @@
     <string name="cut" msgid="3092569408438626261">"ਕੱਟੋ"</string>
     <string name="copy" msgid="2681946229533511987">"ਕਾਪੀ ਕਰੋ"</string>
     <string name="paste" msgid="5629880836805036433">"ਪੇਸਟ ਕਰੋ"</string>
-    <string name="paste_as_plain_text" msgid="5427792741908010675">"ਸਧਾਰਨ ਲਿਖਤ ਦੇ ਤੌਰ \'ਤੇ ਪੇਸਟ ਕਰੋ"</string>
+    <string name="paste_as_plain_text" msgid="5427792741908010675">"ਸਰਲ ਲਿਖਤ ਦੇ ਤੌਰ \'ਤੇ ਪੇਸਟ ਕਰੋ"</string>
     <string name="replace" msgid="5781686059063148930">"ਬਦਲੋ…"</string>
     <string name="delete" msgid="6098684844021697789">"ਮਿਟਾਓ"</string>
     <string name="copyUrl" msgid="2538211579596067402">"URL ਕਾਪੀ ਕਰੋ"</string>
@@ -962,7 +962,7 @@
     <string name="redo" msgid="7759464876566803888">"ਮੁੜ-ਓਹੀ ਕਰੋ"</string>
     <string name="autofill" msgid="3035779615680565188">"ਆਟੋਫਿਲ"</string>
     <string name="textSelectionCABTitle" msgid="5236850394370820357">"ਟੈਕਸਟ ਚੋਣ"</string>
-    <string name="addToDictionary" msgid="4352161534510057874">"ਸ਼ਬਦਕੋਸ਼ ਵਿੱਚ ਜੋੜੋ"</string>
+    <string name="addToDictionary" msgid="4352161534510057874">"ਸ਼ਬਦਕੋਸ਼ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="deleteText" msgid="6979668428458199034">"ਮਿਟਾਓ"</string>
     <string name="inputMethod" msgid="1653630062304567879">"ਇਨਪੁੱਟ ਵਿਧੀ"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"ਟੈਕਸਟ ਕਿਰਿਆਵਾਂ"</string>
@@ -970,9 +970,9 @@
     <string name="dial" msgid="4204975095406423102">"ਫ਼ੋਨ ਕਰੋ"</string>
     <string name="map" msgid="6068210738233985748">"ਨਕਸ਼ੇ"</string>
     <string name="browse" msgid="6993590095938149861">"ਬ੍ਰਾਊਜ਼ਰ"</string>
-    <string name="low_internal_storage_view_title" msgid="5576272496365684834">"ਸਟੋਰੇਜ ਸਪੇਸ ਖ਼ਤਮ ਹੋ ਰਿਹਾ ਹੈ"</string>
+    <string name="low_internal_storage_view_title" msgid="5576272496365684834">"ਸਟੋਰੇਜ ਦੀ ਜਗ੍ਹਾ ਖਤਮ ਹੋ ਰਹੀ ਹੈ"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"ਕੁਝ ਸਿਸਟਮ ਫੰਕਸ਼ਨ ਕੰਮ ਨਹੀਂ ਵੀ ਕਰ ਸਕਦੇ"</string>
-    <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"ਸਿਸਟਮ ਲਈ ਪੂਰੀ ਸਟੋਰੇਜ ਨਹੀਂ। ਯਕੀਨੀ ਬਣਾਓ ਕਿ ਤੁਹਾਡੇ ਕੋਲ 250MB ਖਾਲੀ ਸਪੇਸ ਹੈ ਅਤੇ ਰੀਸਟਾਰਟ ਕਰੋ।"</string>
+    <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"ਸਿਸਟਮ ਲਈ ਲੋੜੀਂਦੀ ਸਟੋਰੇਜ ਨਹੀਂ ਹੈ। ਯਕੀਨੀ ਬਣਾਓ ਕਿ ਤੁਹਾਡੇ ਕੋਲ 250MB ਖਾਲੀ ਜਗ੍ਹਾ ਹੈ ਅਤੇ ਮੁੜ-ਚਾਲੂ ਕਰੋ।"</string>
     <string name="app_running_notification_title" msgid="8718335121060787914">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਚੱਲ ਰਿਹਾ ਹੈ"</string>
     <string name="app_running_notification_text" msgid="1197581823314971177">"ਹੋਰ ਜਾਣਕਾਰੀ ਜਾਂ ਐਪ ਨੂੰ ਬੰਦ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
     <string name="ok" msgid="5970060430562524910">"ਠੀਕ"</string>
@@ -983,14 +983,14 @@
     <string name="loading" msgid="7933681260296021180">"ਲੋਡ ਹੋ ਰਿਹਾ ਹੈ..."</string>
     <string name="capital_on" msgid="1544682755514494298">"ਚਾਲੂ"</string>
     <string name="capital_off" msgid="6815870386972805832">"ਬੰਦ"</string>
-    <string name="whichApplication" msgid="4533185947064773386">"ਇਸਨੂੰ ਵਰਤਦੇ ਹੋਏ ਕਿਰਿਆ ਪੂਰੀ ਕਰੋ"</string>
-    <string name="whichApplicationNamed" msgid="8260158865936942783">"%1$s ਵਰਤਦੇ ਹੋਏ ਕਿਰਿਆ ਪੂਰੀ ਕਰੋ"</string>
+    <string name="whichApplication" msgid="4533185947064773386">"ਇਸਨੂੰ ਵਰਤਦੇ ਹੋਏ ਕਾਰਵਾਈ ਪੂਰੀ ਕਰੋ"</string>
+    <string name="whichApplicationNamed" msgid="8260158865936942783">"%1$s ਵਰਤਦੇ ਹੋਏ ਕਾਰਵਾਈ ਪੂਰੀ ਕਰੋ"</string>
     <string name="whichApplicationLabel" msgid="7425855495383818784">"ਕਾਰਵਾਈ ਪੂਰੀ ਕਰੋ"</string>
     <string name="whichViewApplication" msgid="3272778576700572102">"ਨਾਲ ਖੋਲ੍ਹੋ"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s ਨਾਲ ਖੋਲ੍ਹੋ"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"ਖੋਲ੍ਹੋ"</string>
-    <string name="whichEditApplication" msgid="144727838241402655">"ਨਾਲ ਸੰਪਾਦਿਤ ਕਰੋ"</string>
-    <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s ਨਾਲ ਸੰਪਾਦਿਤ ਕਰੋ"</string>
+    <string name="whichEditApplication" msgid="144727838241402655">"ਇਸ ਨਾਲ ਸੰਪਾਦਨ ਕਰੋ"</string>
+    <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s ਨਾਲ ਸੰਪਾਦਨ ਕਰੋ"</string>
     <string name="whichEditApplicationLabel" msgid="7183524181625290300">"ਸੰਪਾਦਨ ਕਰੋ"</string>
     <string name="whichSendApplication" msgid="6902512414057341668">"ਇਸ ਨਾਲ ਸਾਂਝਾ ਕਰੋ"</string>
     <string name="whichSendApplicationNamed" msgid="2799370240005424391">"%1$s ਨਾਲ ਸਾਂਝਾ ਕਰੋ"</string>
@@ -1004,12 +1004,12 @@
     <string name="whichImageCaptureApplication" msgid="3680261417470652882">"ਇਸ ਨਾਲ ਚਿਤਰ ਕੈਪਚਰ ਕਰੋ"</string>
     <string name="whichImageCaptureApplicationNamed" msgid="8619384150737825003">"%1$s ਨਾਲ ਚਿਤਰ ਕੈਪਚਰ ਕਰੋ"</string>
     <string name="whichImageCaptureApplicationLabel" msgid="6390303445371527066">"ਚਿਤਰ ਕੈਪਚਰ ਕਰੋ"</string>
-    <string name="alwaysUse" msgid="4583018368000610438">"ਇਸ ਕਾਰਵਾਈ ਲਈ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਤੌਰ \'ਤੇ ਵਰਤੋ।"</string>
+    <string name="alwaysUse" msgid="4583018368000610438">"ਇਸ ਕਾਰਵਾਈ ਲਈ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਵਰਤੋ।"</string>
     <string name="use_a_different_app" msgid="8134926230585710243">"ਇੱਕ ਵੱਖਰਾ ਖਾਤਾ ਵਰਤੋ"</string>
     <string name="clearDefaultHintMsg" msgid="3252584689512077257">"ਸਿਸਟਮ ਸੈਟਿੰਗਾਂ &gt; ਐਪਾਂ &gt; ਡਾਊਨਲੋਡ ਕੀਤਿਆਂ ਵਿੱਚ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਹਟਾਓ।"</string>
-    <string name="chooseActivity" msgid="7486876147751803333">"ਇੱਕ ਕਿਰਿਆ ਚੁਣੋ"</string>
+    <string name="chooseActivity" msgid="7486876147751803333">"ਇੱਕ ਕਾਰਵਾਈ ਚੁਣੋ"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"USB ਡੀਵਾਈਸ ਲਈ ਇੱਕ ਐਪ ਚੁਣੋ"</string>
-    <string name="noApplications" msgid="2991814273936504689">"ਕੋਈ ਐਪਸ ਇਸ ਕਿਰਿਆ ਨੂੰ ਨਹੀਂ ਕਰ ਸਕਦੇ।"</string>
+    <string name="noApplications" msgid="2991814273936504689">"ਕੋਈ ਐਪਾਂ ਇਸ ਕਾਰਵਾਈ ਨੂੰ ਨਹੀਂ ਕਰ ਸਕਦੀਆਂ।"</string>
     <string name="aerr_application" msgid="250320989337856518">"<xliff:g id="APPLICATION">%1$s</xliff:g> ਰੁਕ ਗਈ ਹੈ"</string>
     <string name="aerr_process" msgid="6201597323218674729">"<xliff:g id="PROCESS">%1$s</xliff:g> ਰੁਕ ਗਿਆ ਹੈ"</string>
     <string name="aerr_application_repeated" msgid="3146328699537439573">"<xliff:g id="APPLICATION">%1$s</xliff:g> ਵਾਰ-ਵਾਰ ਰੁਕ ਰਹੀ ਹੈ"</string>
@@ -1041,7 +1041,7 @@
     <string name="smv_process" msgid="5120397012047462446">"ਪ੍ਰਕਿਰਿਆ <xliff:g id="PROCESS">%1$s</xliff:g> ਨੇ ਆਪਣੀ ਖੁਦ-ਲਾਗੂ ਕੀਤੀ ਸਟ੍ਰਿਕਟਮੋਡ ਨੀਤੀ ਦੀ ਉਲੰਘਣਾ ਕੀਤੀ ਹੈ।"</string>
     <string name="android_upgrading_title" msgid="1584192285441405746">"Android ਅਪਗ੍ਰੇਡ ਕਰ ਰਿਹਾ ਹੈ…"</string>
     <string name="android_start_title" msgid="8418054686415318207">"Android ਚਾਲੂ ਕਰ ਰਿਹਾ ਹੈ…"</string>
-    <string name="android_upgrading_fstrim" msgid="8036718871534640010">"ਸਟੋਰੇਜ ਅਨੁਕੂਲ ਕਰ ਰਿਹਾ ਹੈ।"</string>
+    <string name="android_upgrading_fstrim" msgid="8036718871534640010">"ਸਟੋਰੇਜ ਅਨੁਕੂਲ ਹੋ ਰਹੀ ਹੈ।"</string>
     <string name="android_upgrading_notification_title" msgid="8428357096969413169">"Android ਅੱਪਡੇਟ ਮੁਕੰਮਲ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
     <string name="android_upgrading_notification_body" msgid="5761201379457064286">"ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਕੁਝ ਐਪਾਂ ਅੱਪਗ੍ਰੇਡ ਪੂਰਾ ਹੋਣ ਤੱਕ ਸਹੀ ਢੰਗ ਨਾਲ ਕੰਮ ਨਾ ਕਰਨ"</string>
     <string name="app_upgrading_toast" msgid="3008139776215597053">"<xliff:g id="APPLICATION">%1$s</xliff:g> ਅੱਪਗ੍ਰੇਡ ਹੋ ਰਹੀ ਹੈ…"</string>
@@ -1060,8 +1060,8 @@
     <string name="dump_heap_notification" msgid="2618183274836056542">"<xliff:g id="PROC">%1$s</xliff:g> ਦੀ ਮੈਮਰੀ ਸੀਮਾ ਵਧ ਗਈ ਹੈ"</string>
     <string name="dump_heap_notification_detail" msgid="6901391084243999274">"ਹੀਪ ਡੰਪ ਇਕੱਤਰ ਕੀਤਾ ਗਿਆ; ਸਾਂਝਾ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="dump_heap_title" msgid="5864292264307651673">"ਕੀ ਹੀਪ ਡੰਪ ਸ਼ੇਅਰ ਕਰਨਾ ਹੈ?"</string>
-    <string name="dump_heap_text" msgid="4809417337240334941">"ਪ੍ਰਕਿਰਿਆ <xliff:g id="PROC">%1$s</xliff:g> ਦੀ ਆਪਣੀ ਪ੍ਰਕਿਰਿਆ ਮੈਮੋਰੀ ਸੀਮਾ <xliff:g id="SIZE">%2$s</xliff:g> ਵਧ ਗਈ ਹੈ। ਇਸਦੇ ਵਿਕਾਸਕਾਰ ਨਾਲ ਸਾਂਂਝਾ ਕਰਨ ਲਈ ਤੁਹਾਡੇ ਲਈ ਇੱਕ ਹੀਪ ਡੰਪ ਉਪਲਬਧ ਹੈ। ਸਾਵਧਾਨ ਰਹੋ: ਇਸ ਹੀਪ ਡੰਪ ਵਿੱਚ ਤੁਹਾਡੀ ਕੋਈ ਵੀ ਨਿੱਜੀ ਜਾਣਕਾਰੀ ਹੋ ਸਕਦੀ ਹੈ, ਜਿਸਤੇ ਐਪਲੀਕੇਸ਼ਨ ਦੀ ਪਹੁੰਚ ਹੈ।"</string>
-    <string name="sendText" msgid="5209874571959469142">"ਟੈਕਸਟ ਲਈ ਇੱਕ ਕਿਰਿਆ ਚੁਣੋ"</string>
+    <string name="dump_heap_text" msgid="4809417337240334941">"ਪ੍ਰਕਿਰਿਆ <xliff:g id="PROC">%1$s</xliff:g> ਦੀ ਆਪਣੀ ਪ੍ਰਕਿਰਿਆ ਮੈਮਰੀ ਸੀਮਾ <xliff:g id="SIZE">%2$s</xliff:g> ਵਧ ਗਈ ਹੈ। ਇਸਦੇ ਵਿਕਾਸਕਾਰ ਨਾਲ ਸਾਂਝਾ ਕਰਨ ਲਈ ਤੁਹਾਡੇ ਲਈ ਇੱਕ ਹੀਪ ਡੰਪ ਉਪਲਬਧ ਹੈ। ਸਾਵਧਾਨ ਰਹੋ: ਇਸ ਹੀਪ ਡੰਪ ਵਿੱਚ ਤੁਹਾਡੀ ਕੋਈ ਵੀ ਨਿੱਜੀ ਜਾਣਕਾਰੀ ਹੋ ਸਕਦੀ ਹੈ, ਜਿਸ \'ਤੇ ਐਪਲੀਕੇਸ਼ਨ ਦੀ ਪਹੁੰਚ ਹੈ।"</string>
+    <string name="sendText" msgid="5209874571959469142">"ਲਿਖਤ ਲਈ ਕੋਈ ਕਾਰਵਾਈ ਚੁਣੋ"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"ਰਿੰਗਰ ਵੌਲਿਊਮ"</string>
     <string name="volume_music" msgid="5421651157138628171">"ਮੀਡੀਆ ਵੌਲਿਊਮ"</string>
     <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"Bluetooth ਰਾਹੀਂ ਪਲੇ ਕਰ ਰਿਹਾ ਹੈ"</string>
@@ -1156,7 +1156,7 @@
     <string name="sim_added_title" msgid="3719670512889674693">"SIM ਕਾਰਡ ਜੋੜਿਆ ਗਿਆ"</string>
     <string name="sim_added_message" msgid="6599945301141050216">"ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਤੱਕ ਪਹੁੰਚ ਲਈ ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਮੁੜ-ਚਾਲੂ ਕਰੋ।"</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"ਰੀਸਟਾਰਟ ਕਰੋ"</string>
-    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"ਤੁਹਾਡੀ ਨਵੀਂ SIM ਦੇ ਸਹੀ ਢੰਗ ਨਾਲ ਕੰਮ ਕਰਨ ਲਈ, ਤੁਹਾਨੂੰ ਤੁਹਾਡੇ ਕੈਰੀਅਰ ਤੋਂ ਇੱਕ ਐਪ ਸਥਾਪਤ ਕਰਨ ਅਤੇ ਖੋਲ੍ਹਣ ਦੀ ਲੋੜ ਪਵੇਗੀ।"</string>
+    <string name="carrier_app_dialog_message" msgid="7066156088266319533">"ਤੁਹਾਡੀ ਨਵੀਂ ਸਿਮ ਦੇ ਸਹੀ ਢੰਗ ਨਾਲ ਕੰਮ ਕਰਨ ਲਈ, ਤੁਹਾਨੂੰ ਤੁਹਾਡੇ ਕੈਰੀਅਰ ਤੋਂ ਇੱਕ ਐਪ ਸਥਾਪਤ ਕਰਨ ਅਤੇ ਖੋਲ੍ਹਣ ਦੀ ਲੋੜ ਪਵੇਗੀ।"</string>
     <string name="carrier_app_dialog_button" msgid="7900235513678617329">"ਐਪ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
     <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"ਅਜੇ ਨਹੀਂ"</string>
     <string name="carrier_app_notification_title" msgid="8921767385872554621">"ਨਵੀਂ SIM ਦਾਖਲ ਕੀਤੀ ਗਈ"</string>
@@ -1178,14 +1178,14 @@
     <string name="usb_accessory_notification_title" msgid="7848236974087653666">"ਇੱਕ USB ਐਕਸੈਸਰੀ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
     <string name="usb_notification_message" msgid="3370903770828407960">"ਹੋਰ ਵਿਕਲਪਾਂ ਲਈ ਟੈਪ ਕਰੋ।"</string>
     <string name="usb_unsupported_audio_accessory_title" msgid="3529881374464628084">"ਐਨਾਲੌਗ  ਆਡੀਓ  ਉਪਸਾਧਨ ਦਾ ਪਤਾ ਲੱਗਿਆ"</string>
-    <string name="usb_unsupported_audio_accessory_message" msgid="6309553946441565215">"ਨੱਥੀ ਕੀਤੀ ਡੀਵਾਈਸ ਇਸ ਫ਼ੋਨ ਦੇ ਅਨੁਰੂਪ ਨਹੀਂ ਹੈ। ਹੋਰ ਜਾਣਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+    <string name="usb_unsupported_audio_accessory_message" msgid="6309553946441565215">"ਨੱਥੀ ਕੀਤਾ ਡੀਵਾਈਸ ਇਸ ਫ਼ੋਨ ਦੇ ਅਨੁਰੂਪ ਨਹੀਂ ਹੈ। ਹੋਰ ਜਾਣਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"USB ਡੀਬਗਿੰਗ ਕਨੈਕਟ ਕੀਤੀ"</string>
     <string name="adb_active_notification_message" msgid="4948470599328424059">"USB ਡੀਬੱਗਿੰਗ ਬੰਦ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
     <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB ਡੀਬੱਗਿੰਗ ਅਯੋਗ ਬਣਾਉਣ ਲਈ ਚੁਣੋ।"</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ਬੱਗ ਰਿਪਰੋਟ ਪ੍ਰਾਪਤ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ..."</string>
     <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"ਕੀ ਬੱਗ ਰਿਪੋਰਟ ਸਾਂਝੀ ਕਰਨੀ ਹੈ?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"ਬੱਗ ਰਿਪੋਰਟ ਸਾਂਝੀ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ…"</string>
-    <string name="share_remote_bugreport_notification_message_finished" msgid="6029609949340992866">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਨੇ ਇਸ ਡੀਵਾਈਸ ਦੀ ਸਮੱਸਿਆ ਨੂੰ ਠੀਕ ਕਰਨ ਵਿੱਚ ਮਦਦ ਲਈ ਬੱਗ ਰਿਪੋਰਟ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਹੈ। ਐਪਾਂ ਅਤੇ ਡਾਟਾ ਨੂੰ ਸਾਂਝਾ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।"</string>
+    <string name="share_remote_bugreport_notification_message_finished" msgid="6029609949340992866">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਨੇ ਇਸ ਡੀਵਾਈਸ ਦੀ ਸਮੱਸਿਆ ਨੂੰ ਠੀਕ ਕਰਨ ਵਿੱਚ ਮਦਦ ਲਈ ਬੱਗ ਰਿਪੋਰਟ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਹੈ। ਐਪਾਂ ਅਤੇ ਡਾਟੇ ਨੂੰ ਸਾਂਝਾ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।"</string>
     <string name="share_remote_bugreport_action" msgid="6249476773913384948">"ਸਾਂਝਾ ਕਰੋ"</string>
     <string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ਅਸਵੀਕਾਰ ਕਰੋ"</string>
     <string name="select_input_method" msgid="8547250819326693584">"ਕੀ-ਬੋਰਡ ਬਦਲੋ"</string>
@@ -1209,7 +1209,7 @@
     <string name="ext_media_unmountable_notification_message" product="tv" msgid="3941179940297874950">"<xliff:g id="NAME">%s</xliff:g> ਖਰਾਬ ਹੈ। ਠੀਕ ਕਰਨ ਲਈ ਚੁਣੋ।"</string>
     <string name="ext_media_unsupported_notification_title" msgid="3797642322958803257">"ਅਸਮਰਥਿਤ <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"ਇਹ ਡੀਵਾਈਸ ਇਸ <xliff:g id="NAME">%s</xliff:g> ਨੂੰ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦਾ ਹੈ। ਕਿਸੇ ਸਮਰਥਿਤ ਫਾਰਮੈਟ ਵਿੱਚ ਸਥਾਪਤ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
-    <string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"ਇਹ ਡੀਵਾਈਸ ਇਸ <xliff:g id="NAME">%s</xliff:g> ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦਾ ਹੈ। ਕਿਸੇ ਸਮਰਥਿਤ ਵੰਨਗੀ ਵਿੱਚ ਸਥਾਪਤ ਕਰਨ ਲਈ ਚੁਣੋ।"</string>
+    <string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"ਇਹ ਡੀਵਾਈਸ ਇਸ <xliff:g id="NAME">%s</xliff:g> ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦਾ ਹੈ। ਕਿਸੇ ਸਮਰਥਿਤ ਫਾਰਮੈਟ ਵਿੱਚ ਸਥਾਪਤ ਕਰਨ ਲਈ ਚੁਣੋ।"</string>
     <string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"<xliff:g id="NAME">%s</xliff:g> ਨੂੰ ਅਚਨਚੇਤ ਹਟਾਇਆ ਗਿਆ"</string>
     <string name="ext_media_badremoval_notification_message" msgid="380176703346946313">"ਡੇਟਾ ਦੇ ਨੁਕਸਾਨ ਤੋਂ ਬੱਚਣ ਲਈ ਹਟਾਉਣ ਤੋਂ ਪਹਿਲਾਂ <xliff:g id="NAME">%s</xliff:g> ਅਨਮਾਊਂਟ ਕਰੋ"</string>
     <string name="ext_media_nomedia_notification_title" msgid="1704840188641749091">"ਹਟਾਇਆ <xliff:g id="NAME">%s</xliff:g>"</string>
@@ -1241,8 +1241,8 @@
     <string name="activity_list_empty" msgid="1675388330786841066">"ਕੋਈ ਮੇਲ ਖਾਂਦੀਆਂ ਗਤੀਵਿਧੀਆਂ ਨਹੀਂ ਮਿਲੀਆਂ।"</string>
     <string name="permlab_route_media_output" msgid="6243022988998972085">"ਰੂਟ ਮੀਡੀਆ ਆਊਟਪੁਟ"</string>
     <string name="permdesc_route_media_output" msgid="4932818749547244346">"ਇੱਕ ਐਪਲੀਕੇਸ਼ਨ ਨੂੂੰ ਹੋਰਾਂ ਬਾਹਰੀ ਡਿਵਾਈਸਾਂ ਲਈ ਮੀਡੀਆ ਆਊਟਪੁਟ ਰੂਟ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
-    <string name="permlab_readInstallSessions" msgid="3713753067455750349">"ਸਥਾਪਿਤ ਸੈਸ਼ਨਾਂ ਨੂੰ ਪੜ੍ਹੋ"</string>
-    <string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ਇੱਕ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਇੰਸਟੌਲ ਸੈਸ਼ਨ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਇਸਨੂੰ ਸਕਿਰਿਆ ਪੈਕੇਜ ਇੰਸਟੌਲੇਸ਼ਨਾਂ ਬਾਰੇ ਵੇਰਵੇ ਦੇਖਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
+    <string name="permlab_readInstallSessions" msgid="3713753067455750349">"ਸਥਾਪਤ ਸੈਸ਼ਨਾਂ ਨੂੰ ਪੜ੍ਹੋ"</string>
+    <string name="permdesc_readInstallSessions" msgid="2049771699626019849">"ਇੱਕ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਸਥਾਪਤ ਸੈਸ਼ਨ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਇਸਨੂੰ ਕਿਰਿਆਸ਼ੀਲ ਪੈਕੇਜ ਸਥਾਪਨਾਵਾਂ ਬਾਰੇ ਵੇਰਵੇ ਦੇਖਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।"</string>
     <string name="permlab_requestInstallPackages" msgid="5782013576218172577">"ਪੈਕੇਜ ਸਥਾਪਤ ਕਰਨ ਦੀ ਬੇਨਤੀ ਕਰੋ"</string>
     <string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"ਪੈਕੇਜ ਦੀ ਸਥਾਪਨਾ ਦੀ ਬੇਨਤੀ ਕਰਨ ਲਈ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਆਗਿਆ ਦਿੰਦਾ ਹੈ"</string>
     <string name="permlab_requestDeletePackages" msgid="1703686454657781242">"ਪੈਕੇਜਾਂ ਨੂੰ ਮਿਟਾਉਣ ਦੀ ਬੇਨਤੀ ਕਰੋ"</string>
@@ -1250,7 +1250,7 @@
     <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"ਬੈਟਰੀ ਸੁਯੋਗਤਾਵਾਂ ਨੂੰ ਅਣਡਿੱਠ ਕਰਨ ਲਈ ਪੁੱਛੋ"</string>
     <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"ਕਿਸੇ ਐਪ ਨੂੰ ਉਸ ਵਾਸਤੇ ਬੈਟਰੀ ਸੁਯੋਗਤਾਵਾਂ ਨੂੰ ਅਣਡਿੱਠ ਕਰਨ ਲਈ ਇਜਾਜ਼ਤ ਵਾਸਤੇ ਪੁੱਛਣ ਲਈ ਆਗਿਆ ਦਿੰਦੀ ਹੈ।"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"ਜ਼ੂਮ ਕੰਟਰੋਲ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰੋ"</string>
-    <string name="gadget_host_error_inflating" msgid="4882004314906466162">"ਵਿਜੇਟ ਨਹੀਂ ਜੋੜ ਸਕਿਆ।"</string>
+    <string name="gadget_host_error_inflating" msgid="4882004314906466162">"ਵਿਜੇਟ ਸ਼ਾਮਲ ਨਹੀਂ ਹੋ ਸਕਿਆ।"</string>
     <string name="ime_action_go" msgid="8320845651737369027">"ਜਾਓ"</string>
     <string name="ime_action_search" msgid="658110271822807811">"ਖੋਜੋ"</string>
     <string name="ime_action_send" msgid="2316166556349314424">"ਭੇਜੋ"</string>
@@ -1320,7 +1320,7 @@
     <string name="sync_too_many_deletes" msgid="5296321850662746890">"ਵਧੀ ਸੀਮਾ ਮਿਟਾਓ"</string>
     <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"<xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>, ਖਾਤੇ <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> ਲਈ <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> ਆਈਟਮਾਂ ਮਿਟਾਈਆਂ ਗਈਆਂ ਹਨ। ਤੁਸੀਂ ਕੀ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
     <string name="sync_really_delete" msgid="2572600103122596243">"ਆਈਟਮਾਂ ਹਟਾਓ"</string>
-    <string name="sync_undo_deletes" msgid="2941317360600338602">"ਮਿਟਾਏ ਗਏ ਅਨਡੂ ਕਰੋ"</string>
+    <string name="sync_undo_deletes" msgid="2941317360600338602">"ਮਿਟਾਏ ਗਏ ਨੂੰ ਅਣਕੀਤਾ ਕਰੋ"</string>
     <string name="sync_do_nothing" msgid="3743764740430821845">"ਹੁਣ ਕੁਝ ਨਾ ਕਰੋ"</string>
     <string name="choose_account_label" msgid="5655203089746423927">"ਇੱਕ ਖਾਤਾ ਚੁਣੋ"</string>
     <string name="add_account_label" msgid="2935267344849993553">"ਇੱਕ ਖਾਤਾ ਸ਼ਾਮਲ ਕਰੋ"</string>
@@ -1354,20 +1354,20 @@
     <string name="activitychooserview_choose_application_error" msgid="8624618365481126668">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> ਨੂੰ ਲਾਂਚ ਨਹੀਂ ਕਰ ਸਕਿਆ"</string>
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"ਇਸ ਨਾਲ ਸਾਂਝਾ ਕਰੋ"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> ਨਾਲ ਸਾਂਝਾ ਕਰੋ"</string>
-    <string name="content_description_sliding_handle" msgid="415975056159262248">"ਹੈਂਡਲ ਸਲਾਈਡ ਕਰ ਰਿਹਾ ਹੈ। ਸਪੱਰਸ਼ ਕਰੋ &amp; ਹੋਲਡ ਕਰੋ।"</string>
-    <string name="description_target_unlock_tablet" msgid="3833195335629795055">"ਅਨਲੌਕ ਕਰਨ ਲਈ ਸਵਾਈਪ ਕਰੋ।"</string>
-    <string name="action_bar_home_description" msgid="5293600496601490216">"ਹੋਮ ਨੈਵੀਗੇਟ ਕਰੋ"</string>
-    <string name="action_bar_up_description" msgid="2237496562952152589">"ਉੱਪਰ ਨੈਵੀਗੇਟ ਕਰੋ"</string>
+    <string name="content_description_sliding_handle" msgid="415975056159262248">"ਹੈਂਡਲ ਸਲਾਈਡ ਕਰ ਰਿਹਾ ਹੈ। ਛੋਹਵੋ &amp; ਹੋਲਡ ਕਰੋ।"</string>
+    <string name="description_target_unlock_tablet" msgid="3833195335629795055">"ਅਣਲਾਕ ਕਰਨ ਲਈ ਸਵਾਈਪ ਕਰੋ।"</string>
+    <string name="action_bar_home_description" msgid="5293600496601490216">"ਹੋਮ \'ਤੇ ਜਾਓ"</string>
+    <string name="action_bar_up_description" msgid="2237496562952152589">"ਉੱਪਰ ਜਾਓ"</string>
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"ਹੋਰ ਚੋਣਾਂ"</string>
     <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="3570990907910199483">"ਅੰਦਰੂਨੀ ਸਾਂਝੀ ਕੀਤੀ ਗਈ ਸਟੋਰੇਜ"</string>
+    <string name="storage_internal" msgid="3570990907910199483">"ਅੰਦਰੂਨੀ ਸਾਂਝੀ ਕੀਤੀ ਸਟੋਰੇਜ"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD ਕਾਰਡ"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD ਕਾਰਡ"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"USB ਡ੍ਰਾਇਵ"</string>
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB ਡ੍ਰਾਇਵ"</string>
     <string name="storage_usb" msgid="3017954059538517278">"USB ਸਟੋਰੇਜ"</string>
-    <string name="extract_edit_menu_button" msgid="8940478730496610137">"ਸੰਪਾਦਿਤ ਕਰੋ"</string>
+    <string name="extract_edit_menu_button" msgid="8940478730496610137">"ਸੰਪਾਦਨ ਕਰੋ"</string>
     <string name="data_usage_warning_title" msgid="3620440638180218181">" ਡਾਟਾ  ਵਰਤੋਂ  ਚਿਤਾਵਨੀ"</string>
     <string name="data_usage_warning_body" msgid="6660692274311972007">"ਵਰਤੋਂ ਅਤੇ ਸੈਟਿੰਗਾਂ ਨੂੰ ਦੇਖਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
     <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"2G-3G ਡਾਟਾ ਸੀਮਾ ਪੂਰੀ ਹੋ ਗਈ"</string>
@@ -1407,13 +1407,13 @@
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ"</string>
     <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"ਟੈਬਲੈੱਟ"</string>
     <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string>
-    <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"ਫੋਨ"</string>
-    <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ਹੈਡਫੋਨ"</string>
+    <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"ਫ਼ੋਨ ਕਰੋ"</string>
+    <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ਹੈੱਡਫ਼ੋਨ"</string>
     <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ਡੌਕ ਸਪੀਕਰਸ"</string>
     <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
     <string name="default_audio_route_category_name" msgid="3722811174003886946">"ਸਿਸਟਮ"</string>
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth  ਆਡੀਓ"</string>
-    <string name="wireless_display_route_description" msgid="9070346425023979651">"ਵਾਇਰਲੈਸ ਡਿਸਪਲੇ"</string>
+    <string name="wireless_display_route_description" msgid="9070346425023979651">"ਵਾਇਰਲੈੱਸ ਡਿਸਪਲੇ"</string>
     <string name="media_route_button_content_description" msgid="591703006349356016">"ਪ੍ਰਸਾਰਿਤ ਕਰੋ"</string>
     <string name="media_route_chooser_title" msgid="1751618554539087622">"ਡੀਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕਰੋ"</string>
     <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"ਡੀਵਾਈਸ ਨਾਲ ਸਕ੍ਰੀਨ ਜੋੜੋ"</string>
@@ -1432,7 +1432,7 @@
     <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", ਸੁਰੱਖਿਅਤ"</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>
+    <string name="kg_wrong_password" msgid="2333281762128113157">"ਗਲਤ ਪਾਸਵਰਡ"</string>
     <string name="kg_wrong_pin" msgid="1131306510833563801">"ਗਲਤ ਪਿੰਨ"</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%1$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"ਆਪਣਾ ਪੈਟਰਨ ਡ੍ਰਾ ਕਰੋ"</string>
@@ -1453,26 +1453,26 @@
     <string name="kg_login_username_hint" msgid="5718534272070920364">"ਵਰਤੋਂਕਾਰ ਨਾਮ (ਈਮੇਲ)"</string>
     <string name="kg_login_password_hint" msgid="9057289103827298549">"ਪਾਸਵਰਡ"</string>
     <string name="kg_login_submit_button" msgid="5355904582674054702">"ਸਾਈਨ-ਇਨ ਕਰੋ"</string>
-    <string name="kg_login_invalid_input" msgid="5754664119319872197">"ਅਪ੍ਰਮਾਣਿਕ ਵਰਤੋਂਕਾਰ ਨਾਮ ਜਾਂ ਪਾਸਵਰਡ।"</string>
+    <string name="kg_login_invalid_input" msgid="5754664119319872197">"ਅਵੈਧ ਵਰਤੋਂਕਾਰ ਨਾਮ ਜਾਂ ਪਾਸਵਰਡ।"</string>
     <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"ਕੀ ਤੁਸੀਂ ਆਪਣਾ ਵਰਤੋਂਕਾਰ ਨਾਮ ਜਾਂ ਪਾਸਵਰਡ ਭੁੱਲ ਗਏ ਹੋ?\n"<b>"google.com/accounts/recovery"</b>" ਤੇ ਜਾਓ।"</string>
     <string name="kg_login_checking_password" msgid="1052685197710252395">"ਖਾਤੇ ਦੀ ਜਾਂਚ ਕਰ ਰਿਹਾ ਹੈ…"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"ਤੁਸੀਂ ਆਪਣਾ ਪਿੰਨ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟਾਈਪ ਕੀਤਾ ਹੈ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਪਾਸਵਰਡ ਗ਼ਲਤ ਢੰਗ ਨਾਲ ਟਾਈਪ ਕੀਤਾ ਹੈ। \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
-    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਨਲੌਕ ਪੈਟਰਨ ਗ਼ਲਤ ਢੰਗ ਨਾਲ ਡ੍ਰਾ ਕੀਤਾ ਹੈ। \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
-    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਟੈਬਲੈੱਟ ਫੈਕਟਰੀ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਤੇ ਰੀਸੈੱਟ ਹੋ ਜਾਵੇਗਾ ਅਤੇ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡਾਟਾ ਨਸ਼ਟ ਹੋ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਪਾਸਵਰਡ ਗਲਤ ਢੰਗ ਨਾਲ ਟਾਈਪ ਕੀਤਾ ਹੈ।\n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ ਹੈ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਵੱਧ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਟੈਬਲੈੱਟ ਫੈਕਟਰੀ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਤੇ ਰੀਸੈੱਟ ਹੋ ਜਾਵੇਗਾ ਅਤੇ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡਾਟਾ ਨਸ਼ਟ ਹੋ ਜਾਵੇਗਾ।"</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="5621231220154419413">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੀਵੀ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਵੱਧ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਟੀਵੀ ਫੈਕਟਰੀ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਤੇ ਰੀਸੈੱਟ ਹੋ ਜਾਏਗਾ ਅਤੇ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡਾਟਾ ਨਸ਼ਟ ਹੋ ਜਾਏਗਾ।"</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਵੱਧ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਫ਼ੋਨ ਫੈਕਟਰੀ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਤੇ ਰੀਸੈੱਟ ਹੋ ਜਾਏਗਾ ਅਤੇ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡਾਟਾ ਨਸ਼ਟ ਹੋ ਜਾਏਗਾ।"</string>
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। ਹੁਣ ਟੈਬਲੈੱਟ ਫੈਕਟਰੀ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਤੇ ਰੀਸੈੱਟ ਹੋ ਜਾਵੇਗਾ।"</string>
     <string name="kg_failed_attempts_now_wiping" product="tv" msgid="4987878286750741463">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੀਵੀ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। ਹੁਣ ਟੀਵੀ ਫੈਕਟਰੀ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਤੇ ਰੀਸੈੱਟ ਹੋ ਜਾਏਗਾ।"</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ। ਹੁਣ ਫ਼ੋਨ ਫੈਕਟਰੀ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਤੇ ਰੀਸੈੱਟ ਹੋ ਜਾਏਗਾ।"</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣਾ ਟੈਬਲੈੱਟ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਵੇਗਾ।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣੇ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਵੇਗਾ।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਡ੍ਰਾ ਕੀਤਾ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣਾ ਟੀਵੀ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਏਗਾ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਨਲੌਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਡ੍ਰਾ ਕੀਤਾ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣਾ ਫ਼ੋਨ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਵੇਗਾ।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਡ੍ਰਾ ਕੀਤਾ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣਾ ਫ਼ੋਨ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਏਗਾ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"ਹਟਾਓ"</string>
     <string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"ਕੀ ਵੌਲਿਊਮ  ਸਿਫ਼ਾਰਸ਼  ਕੀਤੇ ਪੱਧਰ ਤੋਂ ਵਧਾਉਣੀ ਹੈ?\n\nਲੰਮੇ ਸਮੇਂ ਤੱਕ ਉੱਚ ਵੌਲਿਊਮ ਤੇ ਸੁਣਨ ਨਾਲ ਤੁਹਾਡੀ ਸੁਣਨ ਸ਼ਕਤੀ ਨੂੰ ਨੁਕਸਾਨ ਪਹੁੰਚ ਸਕਦਾ ਹੈ।"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="8404780875025725199">"ਕੀ ਪਹੁੰਚਯੋਗਤਾ ਸ਼ਾਰਟਕੱਟ ਵਰਤਣਾ ਹੈ?"</string>
-    <string name="accessibility_shortcut_toogle_warning" msgid="7256507885737444807">"ਸ਼ਾਰਟਕੱਟ ਚਾਲੂ ਹੋਣ \'ਤੇ, ਕਿਸੇ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਵੌਲਿਊਮ ਬਟਨਾਂ ਨੂੰ 3 ਸਕਿੰਟ ਲਈ ਦਬਾ ਕੇ ਰੱਖੋ।\n\n ਵਰਤਮਾਨ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾ:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ਤੁਸੀਂ ਸੈਟਿੰਗਾਂ &gt; ਪਹੁੰਚਯੋਗਤਾ ਵਿੱਚ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਬਦਲ ਸਕਦੇ ਹੋ।"</string>
+    <string name="accessibility_shortcut_toogle_warning" msgid="7256507885737444807">"ਸ਼ਾਰਟਕੱਟ ਚਾਲੂ ਹੋਣ \'ਤੇ, ਕਿਸੇ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਅਵਾਜ਼ ਬਟਨਾਂ ਨੂੰ 3 ਸਕਿੰਟ ਲਈ ਦਬਾ ਕੇ ਰੱਖੋ।\n\n ਵਰਤਮਾਨ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾ:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ਤੁਸੀਂ ਸੈਟਿੰਗਾਂ &gt; ਪਹੁੰਚਯੋਗਤਾ ਵਿੱਚ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਬਦਲ ਸਕਦੇ ਹੋ।"</string>
     <string name="disable_accessibility_shortcut" msgid="627625354248453445">"ਸ਼ਾਰਟਕੱਟ ਬੰਦ ਕਰੋ"</string>
     <string name="leave_accessibility_shortcut_on" msgid="7653111894438512680">"ਸ਼ਾਰਟਕੱਟ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="7771852911861522636">"ਪਹੁੰਚਯੋਗਤਾ ਸ਼ਾਰਟਕੱਟ ਨੇ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਨੂੰ ਚਾਲੂ ਕੀਤਾ"</string>
@@ -1486,7 +1486,7 @@
     <string name="owner_name" msgid="2716755460376028154">"ਮਾਲਕ"</string>
     <string name="error_message_title" msgid="4510373083082500195">"ਅਸ਼ੁੱਧੀ"</string>
     <string name="error_message_change_not_allowed" msgid="1238035947357923497">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਇਸ ਤਬਦੀਲੀ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਹੈ"</string>
-    <string name="app_not_found" msgid="3429141853498927379">"ਇਸ ਕਿਰਿਆ ਨੂੰ ਸੰਭਾਲਣ ਲਈ ਕੋਈ ਐਪਲੀਕੇਸ਼ਨ ਨਹੀਂ ਮਿਲੀ।"</string>
+    <string name="app_not_found" msgid="3429141853498927379">"ਇਸ ਕਾਰਵਾਈ ਨੂੰ ਸੰਭਾਲਣ ਲਈ ਕੋਈ ਐਪਲੀਕੇਸ਼ਨ ਨਹੀਂ ਮਿਲੀ।"</string>
     <string name="revoke" msgid="5404479185228271586">"ਰੱਦ ਕਰੋ"</string>
     <string name="mediasize_iso_a0" msgid="1994474252931294172">"ISO A0"</string>
     <string name="mediasize_iso_a1" msgid="3333060421529791786">"ISO A1"</string>
@@ -1610,13 +1610,13 @@
     <string name="lock_to_app_start" msgid="6643342070839862795">"ਸਕ੍ਰੀਨ ਪਿੰਨ ਕੀਤੀ"</string>
     <string name="lock_to_app_exit" msgid="8598219838213787430">"ਸਕ੍ਰੀਨ ਅਨਪਿਨ ਕੀਤੀ"</string>
     <string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"ਅਨਪਿੰਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਪਿੰਨ ਮੰਗੋ"</string>
-    <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ਅਨਪਿਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਅਨਲੌਕ ਪੈਟਰਨ ਵਾਸਤੇ ਪੁੱਛੋ"</string>
-    <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ਅਨਪਿਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਪਾਸਵਰਡ ਮੰਗੋ"</string>
+    <string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"ਅਨਪਿੰਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਅਣਲਾਕ ਪੈਟਰਨ ਵਾਸਤੇ ਪੁੱਛੋ"</string>
+    <string name="lock_to_app_unlock_password" msgid="6380979775916974414">"ਅਨਪਿੰਨ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਪਾਸਵਰਡ ਮੰਗੋ"</string>
     <string name="package_installed_device_owner" msgid="6875717669960212648">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਸਥਾਪਤ ਕੀਤਾ ਗਿਆ"</string>
     <string name="package_updated_device_owner" msgid="1847154566357862089">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਅੱਪਡੇਟ ਕੀਤਾ ਗਿਆ"</string>
     <string name="package_deleted_device_owner" msgid="2307122077550236438">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਮਿਟਾਇਆ ਗਿਆ"</string>
-    <string name="battery_saver_description" msgid="1960431123816253034">"ਬੈਟਰੀ ਲਾਈਫ਼ ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਣ ਵਿੱਚ ਮਦਦ ਕਰਨ ਲਈ, ਬੈਟਰੀ ਸੇਵਰ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਦਰਸ਼ਨ ਘਟਾਉਂਦਾ ਹੈ ਅਤੇ ਵਾਈਬ੍ਰੇਸ਼ਨ, ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਅਤੇ ਜ਼ਿਆਦਾਤਰ ਬੈਕਗ੍ਰਾਊਂਡ ਡਾਟਾ ਨੂੰ ਸੀਮਿਤ ਕਰਦਾ ਹੈ। ਈਮੇਲ, ਸੁਨੇਹਾ ਭੇਜਣ ਅਤੇ ਹੋਰ ਐਪਾਂ, ਜੋ ਸਮਕਾਲੀਕਰਨ \'ਤੇ ਨਿਰਭਰ ਹਨ, ਉਹ ਉਦੋਂ ਤੱਕ ਅੱਪਡੇਟ ਨਹੀਂ ਕੀਤੇ ਜਾ ਸਕਦੇ ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਉਹਨਾਂ ਨੂੰ ਖੋਲ੍ਹਦੇ ਨਹੀਂ।\n\nਬੈਟਰੀ ਸੇਵਰ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਬੰਦ ਹੁੰਦਾ ਹੈ ਜਦੋਂ ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੁੰਦਾ ਹੈ।"</string>
-    <string name="data_saver_description" msgid="6015391409098303235">"ਡਾਟਾ ਵਰਤੋਂ ਘਟਾਉਣ ਵਿੱਚ ਮਦਦ ਲਈ, ਡਾਟਾ ਸੇਵਰ ਕੁਝ ਐਪਾਂ ਨੂੰ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਡਾਟਾ ਭੇਜਣ ਜਾਂ ਪ੍ਰਾਪਤ ਕਰਨ ਤੋਂ ਰੋਕਦਾ ਹੈ। ਤੁਹਾਡੇ ਵੱਲੋਂ ਵਰਤਮਾਨ ਤੌਰ \'ਤੇ ਵਰਤੀ ਜਾ ਰਹੀ ਐਪ ਡਾਟਾ \'ਤੇ ਪਹੁੰਚ ਕਰ ਸਕਦੀ ਹੈ, ਪਰ ਉਹ ਇੰਝ ਕਦੇ-ਕਦਾਈਂ ਕਰ ਸਕਦੀ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਇਸ ਦਾ ਮਤਲਬ ਇਹ ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਚਿੱਤਰ ਤਦ ਤੱਕ ਨਹੀਂ ਦਿਖਾਏ ਜਾਂਦੇ, ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਉਹਨਾਂ \'ਤੇ ਟੈਪ ਨਹੀਂ ਕਰਦੇ।"</string>
+    <string name="battery_saver_description" msgid="1960431123816253034">"ਬੈਟਰੀ ਲਾਈਫ਼ ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਣ ਵਿੱਚ ਸਹਾਇਤਾ ਕਰਨ ਲਈ, ਬੈਟਰੀ ਸੇਵਰ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਦਰਸ਼ਨ ਘਟਾਉਂਦਾ ਹੈ ਅਤੇ ਵਾਈਬ੍ਰੇਸ਼ਨ, ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਅਤੇ ਜ਼ਿਆਦਾਤਰ ਬੈਕਗ੍ਰਾਊਂਡ ਡਾਟੇ ਨੂੰ ਸੀਮਿਤ ਕਰਦਾ ਹੈ। ਈਮੇਲ, ਸੁਨੇਹਾ ਭੇਜਣ ਅਤੇ ਹੋਰ ਐਪਾਂ, ਜੋ ਸਮਕਾਲੀਕਰਨ \'ਤੇ ਨਿਰਭਰ ਹਨ, ਉਹ ਉਦੋਂ ਤੱਕ ਅੱਪਡੇਟ ਨਹੀਂ ਕੀਤੇ ਜਾ ਸਕਦੇ ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਉਹਨਾਂ ਨੂੰ ਖੋਲ੍ਹਦੇ ਨਹੀਂ।\n\nਬੈਟਰੀ ਸੇਵਰ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਬੰਦ ਹੁੰਦਾ ਹੈ ਜਦੋਂ ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੁੰਦਾ ਹੈ।"</string>
+    <string name="data_saver_description" msgid="6015391409098303235">"ਡਾਟਾ ਵਰਤੋਂ ਘਟਾਉਣ ਵਿੱਚ ਮਦਦ ਲਈ, ਡਾਟਾ ਸੇਵਰ ਕੁਝ ਐਪਾਂ ਨੂੰ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਡਾਟਾ ਭੇਜਣ ਜਾਂ ਪ੍ਰਾਪਤ ਕਰਨ ਤੋਂ ਰੋਕਦਾ ਹੈ। ਤੁਹਾਡੇ ਵੱਲੋਂ ਵਰਤਮਾਨ ਤੌਰ \'ਤੇ ਵਰਤੀ ਜਾ ਰਹੀ ਐਪ ਡਾਟਾ \'ਤੇ ਪਹੁੰਚ ਕਰ ਸਕਦੀ ਹੈ, ਪਰ ਉਹ ਇੰਝ ਕਦੇ-ਕਦਾਈਂ ਕਰ ਸਕਦੀ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਇਸ ਦਾ ਮਤਲਬ ਇਹ ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਚਿੱਤਰ ਤਦ ਤੱਕ ਨਹੀਂ ਪ੍ਰਦਰਸ਼ਿਤ ਕੀਤੇ ਜਾਂਦੇ, ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਉਹਨਾਂ \'ਤੇ ਟੈਪ ਨਹੀਂ ਕਰਦੇ।"</string>
     <string name="data_saver_enable_title" msgid="4674073932722787417">"ਕੀ ਡਾਟਾ ਸੇਵਰ ਚਾਲੂ ਕਰਨਾ ਹੈ?"</string>
     <string name="data_saver_enable_button" msgid="7147735965247211818">"ਚਾਲੂ ਕਰੋ"</string>
     <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
@@ -1698,25 +1698,25 @@
     <string name="language_picker_section_suggested" msgid="8414489646861640885">"ਸੁਝਾਈਆਂ ਗਈਆਂ"</string>
     <string name="language_picker_section_all" msgid="3097279199511617537">"ਸਾਰੀਆਂ ਭਾਸ਼ਾਵਾਂ"</string>
     <string name="region_picker_section_all" msgid="8966316787153001779">"ਸਾਰੇ ਖੇਤਰ"</string>
-    <string name="locale_search_menu" msgid="2560710726687249178">"ਖੋਜ"</string>
+    <string name="locale_search_menu" msgid="2560710726687249178">"ਖੋਜੋ"</string>
     <string name="work_mode_off_title" msgid="2615362773958585967">"ਕੀ ਕਾਰਜ ਮੋਡ ਚਾਲੂ ਕਰੀਏ?"</string>
     <string name="work_mode_off_message" msgid="2961559609199223594">"ਇਸ ਨਾਲ ਐਪਾਂ, ਬੈਕਗ੍ਰਾਊਂਡ ਸਮਕਾਲੀਕਰਨ, ਅਤੇ ਸਬੰਧਿਤ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਸਮੇਤ ਤੁਹਾਡੇ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਜਾਵੇਗਾ"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"ਚਾਲੂ ਕਰੋ"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"ਤੁਹਾਨੂੰ ਨਵੇਂ ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਹੋਏ ਹਨ"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"ਦੇਖਣ ਲਈ SMS ਐਪ ਖੋਲ੍ਹੋ"</string>
     <string name="user_encrypted_title" msgid="9054897468831672082">"ਕੁਝ ਪ੍ਰਕਾਰਜਾਤਮਕਤਾ ਸੀਮਿਤ ਹੋ ਸਕਦੀ ਹੈ"</string>
-    <string name="user_encrypted_message" msgid="4923292604515744267">"ਅਨਲੌਕ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
+    <string name="user_encrypted_message" msgid="4923292604515744267">"ਅਣਲਾਕ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="user_encrypted_detail" msgid="5708447464349420392">"ਵਰਤੋਂਕਾਰ  ਡਾਟਾ  ਲੌਕ ਕੀਤਾ ਗਿਆ"</string>
     <string name="profile_encrypted_detail" msgid="3700965619978314974">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਲਾਕ ਕੀਤੀ ਗਈ"</string>
     <string name="profile_encrypted_message" msgid="6964994232310195874">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="usb_mtp_launch_notification_title" msgid="8359219638312208932">"<xliff:g id="PRODUCT_NAME">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੋਈ"</string>
-    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"ਫ਼ਾਈਲਾਂ ਵੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
+    <string name="usb_mtp_launch_notification_description" msgid="8541876176425411358">"ਫ਼ਾਈਲਾਂ ਦੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="pin_target" msgid="3052256031352291362">"ਪਿੰਨ ਕਰੋ"</string>
     <string name="unpin_target" msgid="3556545602439143442">"ਅਨਪਿੰਨ ਕਰੋ"</string>
     <string name="app_info" msgid="6856026610594615344">"ਐਪ ਜਾਣਕਾਰੀ"</string>
     <string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="demo_starting_message" msgid="5268556852031489931">"ਡੈਮੋ ਚਾਲੂ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
-    <string name="demo_restarting_message" msgid="952118052531642451">"ਡੀਵਾਈਸ ਮੁੜ-ਸੈੱਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
+    <string name="demo_restarting_message" msgid="952118052531642451">"ਡੀਵਾਈਸ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
     <string name="suspended_widget_accessibility" msgid="6712143096475264190">"ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="conference_call" msgid="3751093130790472426">"ਕਾਨਫਰੰਸ ਕਾਲ"</string>
     <string name="tooltip_popup_title" msgid="5253721848739260181">"ਟੂਲ-ਟਿੱਪ"</string>
@@ -1745,10 +1745,10 @@
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> ਆਟੋਫਿਲ ਸੁਝਾਅ</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> ਆਟੋਫਿਲ ਸੁਝਾਅ</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਰੱਖਿਅਤ ਕਰੀਏ?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> ਨੂੰ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਰੱਖਿਅਤ ਕਰੀਏ?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> ਅਤੇ <xliff:g id="TYPE_1">%2$s</xliff:g> ਨੂੰ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਰੱਖਿਅਤ ਕਰੀਏ?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ਅਤੇ <xliff:g id="TYPE_2">%3$s</xliff:g> ਨੂੰ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਰੱਖਿਅਤ ਕਰੀਏ?"</string>
+    <string name="autofill_save_title" msgid="3345527308992082601">"ਕੀ &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਰੱਖਿਅਤ ਕਰਨਾ ਹੈ?"</string>
+    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"ਕੀ <xliff:g id="TYPE">%1$s</xliff:g> ਨੂੰ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਰੱਖਿਅਤ ਕਰਨਾ ਹੈ?"</string>
+    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"ਕੀ <xliff:g id="TYPE_0">%1$s</xliff:g> ਅਤੇ <xliff:g id="TYPE_1">%2$s</xliff:g> ਨੂੰ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਰੱਖਿਅਤ ਕਰਨਾ ਹੈ?"</string>
+    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"ਕੀ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ਅਤੇ <xliff:g id="TYPE_2">%3$s</xliff:g> ਨੂੰ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਰੱਖਿਅਤ ਕਰਨਾ ਹੈ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"ਰੱਖਿਅਤ ਕਰੋ"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"ਨਹੀਂ ਧੰਨਵਾਦ"</string>
     <string name="autofill_save_type_password" msgid="5288448918465971568">"ਪਾਸਵਰਡ"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 3eb9798..1cc7d5a 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -133,7 +133,7 @@
     <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Само Wi-Fi"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Није прослеђено"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
-    <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> након <xliff:g id="TIME_DELAY">{2}</xliff:g> секунде(и)"</string>
+    <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> након <xliff:g id="TIME_DELAY">{2}</xliff:g> секунде/и"</string>
     <string name="cfTemplateRegistered" msgid="5073237827620166285">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Није прослеђено"</string>
     <string name="cfTemplateRegisteredTime" msgid="6781621964320635172">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: Није прослеђено"</string>
     <string name="fcComplete" msgid="3118848230966886575">"Кôд функције је извршен."</string>
@@ -730,19 +730,19 @@
     <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"Погледајте Кориснички водич или контактирајте Корисничку подршку."</string>
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM картица је закључана."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Откључавање SIM картице…"</string>
-    <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"<xliff:g id="NUMBER_0">%1$d</xliff:g> пута сте неправилно нацртали шаблон за откључавање. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
-    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"<xliff:g id="NUMBER_0">%1$d</xliff:g> пута сте погрешно унели лозинку. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
-    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"<xliff:g id="NUMBER_0">%1$d</xliff:g> пута сте погрешно унели PIN. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"<xliff:g id="NUMBER_0">%1$d</xliff:g> пута сте нетачно унели шаблон за откључавање. Након још <xliff:g id="NUMBER_1">%2$d</xliff:g> несупешна(их) покушаја, од вас ће бити затражено да откључате таблет помоћу података за пријављивање на Google.\n\n Пробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде(и)."</string>
+    <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"<xliff:g id="NUMBER_0">%1$d</xliff:g> пута сте неправилно нацртали шаблон за откључавање. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде/и."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"<xliff:g id="NUMBER_0">%1$d</xliff:g> пута сте погрешно унели лозинку. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде/и."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"<xliff:g id="NUMBER_0">%1$d</xliff:g> пута сте погрешно унели PIN. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде/и."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"<xliff:g id="NUMBER_0">%1$d</xliff:g> пута сте нетачно унели шаблон за откључавање. Након још <xliff:g id="NUMBER_1">%2$d</xliff:g> несупешна(их) покушаја, од вас ће бити затражено да откључате таблет помоћу података за пријављивање на Google.\n\n Пробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде/и."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"Неисправно сте нацртали шаблон за откључавање <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја од вас ће бити затражено да откључате ТВ помоћу података за пријављивање на Google.\n\n Пробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"<xliff:g id="NUMBER_0">%1$d</xliff:g> пута сте нетачно унели шаблон за откључавање. Након још <xliff:g id="NUMBER_1">%2$d</xliff:g> несупешна(их) покушаја, од вас ће бити затражено да откључате телефон помоћу података за пријављивање на Google.\n\n Пробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде(и)."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"<xliff:g id="NUMBER_0">%1$d</xliff:g> пута сте нетачно унели шаблон за откључавање. Након још <xliff:g id="NUMBER_1">%2$d</xliff:g> несупешна(их) покушаја, од вас ће бити затражено да откључате телефон помоћу података за пријављивање на Google.\n\n Пробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде/и."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Неправилно сте покушали да откључате таблет <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Након још неуспешних покушаја (<xliff:g id="NUMBER_1">%2$d</xliff:g>) таблет ће бити ресетован на фабричка подешавања и сви кориснички подаци ће бити изгубљени."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="950408382418270260">"Покушали сте да откључате ТВ нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја ТВ ће бити ресетован на подразумевана фабричка подешавања и сви кориснички подаци ће бити изгубљени."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Неисправно сте покушали да откључате телефон <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Након још неуспешних покушаја (<xliff:g id="NUMBER_1">%2$d</xliff:g>) телефон ће бити ресетован на фабричка подешавања и сви кориснички подаци ће бити изгубљени."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"Неисправно сте покушали да откључате таблет <xliff:g id="NUMBER">%d</xliff:g> пута. Таблет ће сада бити враћен на подразумевана фабричка подешавања."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="3195755534096192191">"Покушали сте да откључате ТВ нетачно <xliff:g id="NUMBER">%d</xliff:g> пута. ТВ ће сада бити ресетован на подразумевана фабричка подешавања."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Неисправно сте покушали да откључате телефон <xliff:g id="NUMBER">%d</xliff:g> пута. Телефон ће сада бити враћен на подразумевана фабричка подешавања."</string>
-    <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Пробајте поново за <xliff:g id="NUMBER">%d</xliff:g> секунде(и)."</string>
+    <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Пробајте поново за <xliff:g id="NUMBER">%d</xliff:g> секунде/и."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Заборавили сте шаблон?"</string>
     <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Откључавање налога"</string>
     <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"Превише покушаја уноса шаблона"</string>
@@ -874,7 +874,7 @@
     <string name="second" msgid="3184235808021478">"сек"</string>
     <string name="seconds" msgid="3161515347216589235">"сек"</string>
     <string name="week" msgid="5617961537173061583">"недеља"</string>
-    <string name="weeks" msgid="6509623834583944518">"недеље(а)"</string>
+    <string name="weeks" msgid="6509623834583944518">"недеље/а"</string>
     <string name="year" msgid="4001118221013892076">"година"</string>
     <string name="years" msgid="6881577717993213522">"годинe(а)"</string>
     <string name="now_string_shortest" msgid="8912796667087856402">"сада"</string>
@@ -1457,7 +1457,7 @@
     <string name="kg_wrong_pattern" msgid="1850806070801358830">"Погрешан шаблон"</string>
     <string name="kg_wrong_password" msgid="2333281762128113157">"Погрешна лозинка"</string>
     <string name="kg_wrong_pin" msgid="1131306510833563801">"Погрешан PIN"</string>
-    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Пробајте поново за <xliff:g id="NUMBER">%1$d</xliff:g> секунде(и)."</string>
+    <string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"Пробајте поново за <xliff:g id="NUMBER">%1$d</xliff:g> секунде/и."</string>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"Нацртајте шаблон"</string>
     <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Унесите PIN SIM картице"</string>
     <string name="kg_pin_instructions" msgid="2377242233495111557">"Унесите PIN"</string>
@@ -1479,18 +1479,18 @@
     <string name="kg_login_invalid_input" msgid="5754664119319872197">"Неважеће корисничко име или лозинка."</string>
     <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"Заборавили сте корисничко име или лозинку?\nПосетите адресу "<b>"google.com/accounts/recovery"</b>"."</string>
     <string name="kg_login_checking_password" msgid="1052685197710252395">"Провера налога…"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Унели сте нетачни PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Унели сте нетачну лозинку <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
-    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде(и)."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"Унели сте нетачни PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде/и."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"Унели сте нетачну лозинку <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде/и."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунде/и."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"Покушали сте да откључате таблет нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. Након још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја таблет ће бити ресетован на фабричка подешавања и сви кориснички подаци ће бити изгубљени."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tv" msgid="5621231220154419413">"Покушали сте да откључате ТВ нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја ТВ ће бити ресетован на подразумевана фабричка подешавања и сви кориснички подаци ће бити изгубљени."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"Покушали сте да откључате телефон нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја телефон ће бити ресетован на фабричка подешавања и сви кориснички подаци ће бити изгубљени."</string>
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Покушали сте да откључате таблет нетачно <xliff:g id="NUMBER">%d</xliff:g> пута. Таблет ће сада бити враћен на подразумевана фабричка подешавања."</string>
     <string name="kg_failed_attempts_now_wiping" product="tv" msgid="4987878286750741463">"Покушали сте да откључате ТВ нетачно <xliff:g id="NUMBER">%d</xliff:g> пута. ТВ ће сада бити ресетован на подразумевана фабричка подешавања."</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Покушали сте да откључате телефон нетачно <xliff:g id="NUMBER">%d</xliff:g> пута. Телефон ће сада бити враћен на подразумевана фабричка подешавања."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате таблет помоћу налога е-поште.\n\nПробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде(и)."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате таблет помоћу налога е-поште.\n\nПробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде/и."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"Неисправно сте нацртали шаблон за откључавање <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате ТВ помоћу налога е-поште.\n\n Пробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате телефон помоћу налога е-поште.\n\nПробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде(и)."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате телефон помоћу налога е-поште.\n\nПробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде/и."</string>
     <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Уклони"</string>
     <string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"Желите да појачате звук изнад препорученог нивоа?\n\nСлушање гласне музике дуже време може да вам оштети слух."</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 15d593b..105ef44 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1891,6 +1891,7 @@
         <enum name="KEYCODE_SYSTEM_NAVIGATION_DOWN" value="281" />
         <enum name="KEYCODE_SYSTEM_NAVIGATION_LEFT" value="282" />
         <enum name="KEYCODE_SYSTEM_NAVIGATION_RIGHT" value="283" />
+        <enum name="KEYCODE_ALL_APPS" value="284" />
     </attr>
 
     <!-- ***************************************************************** -->
@@ -2096,16 +2097,15 @@
              -->
         <attr name="windowSplashscreenContent" format="reference" />
 
-        <!-- @hide
-             If set, the navigation bar will be drawn such that it is compatible with a light
-             navigation bar background.
+        <!-- @hide If set, the navigation bar will be drawn such that it is
+             compatible with a light navigation bar background.
              <p>For this to take effect, the window must be drawing the system bar backgrounds with
              {@link android.R.attr#windowDrawsSystemBarBackgrounds} and the navigation bar must not
              have been requested to be translucent with
              {@link android.R.attr#windowTranslucentNavigation}.
              Corresponds to setting {@link android.view.View#SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR} on
              the decor view. -->
-        <attr name="windowLightNavigationBar" format="boolean" />
+         <attr name="windowLightNavigationBar" format="boolean" />
     </declare-styleable>
 
     <!-- The set of attributes that describe a AlertDialog's theme. -->
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 9b1ebc8..2c64789 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -346,6 +346,11 @@
     <dimen name="notification_text_size">14sp</dimen>
     <!-- Size of notification text titles (see TextAppearance.StatusBar.EventContent.Title) -->
     <dimen name="notification_title_text_size">14sp</dimen>
+
+    <!-- Size of notification text (see TextAppearance.StatusBar.EventContent) when colorized -->
+    <dimen name="notification_text_size_colorized">16sp</dimen>
+    <!-- Size of notification text titles (see TextAppearance.StatusBar.EventContent.Title) when colorized -->
+    <dimen name="notification_title_text_size_colorized">20sp</dimen>
     <!-- Size of smaller notification text (see TextAppearance.StatusBar.EventContent.Line2, Info, Time) -->
     <dimen name="notification_subtext_size">12sp</dimen>
 
@@ -604,4 +609,11 @@
     <!-- Max height of the the autofill save custom subtitle as a fraction of the screen width/height -->
     <dimen name="autofill_save_custom_subtitle_max_height">20%</dimen>
 
+    <!-- Max (absolute) dimensions (both width and height) of autofill service icon on autofill save affordance.
+      NOTE: the actual displayed size might is actually smaller than this and is hardcoded in the
+      autofill_save.xml layout; this dimension is just used to avoid a crash in the UI (if the icon provided
+      by the autofill service metadata is bigger than these dimentionsit will not be displayed).
+    -->
+    <dimen name="autofill_save_icon_max_size">300dp</dimen>
+
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 8c10a8d..db3dfa4d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2900,8 +2900,9 @@
   <java-symbol type="id" name="autofill_dataset_list"/>
   <java-symbol type="id" name="autofill" />
   <java-symbol type="id" name="autofill_save_custom_subtitle" />
-  <java-symbol type="id" name="autofill_save_title" />
+  <java-symbol type="id" name="autofill_save_icon" />
   <java-symbol type="id" name="autofill_save_no" />
+  <java-symbol type="id" name="autofill_save_title" />
   <java-symbol type="id" name="autofill_save_yes" />
   <java-symbol type="string" name="autofill_error_cannot_autofill" />
   <java-symbol type="string" name="autofill_picker_no_suggestions" />
@@ -2925,6 +2926,7 @@
   <java-symbol type="style" name="AutofillSaveAnimation" />
   <java-symbol type="dimen" name="autofill_dataset_picker_max_size"/>
   <java-symbol type="dimen" name="autofill_save_custom_subtitle_max_height"/>
+  <java-symbol type="dimen" name="autofill_save_icon_max_size"/>
 
   <java-symbol type="dimen" name="notification_big_picture_max_height"/>
   <java-symbol type="dimen" name="notification_big_picture_max_width"/>
@@ -3048,6 +3050,9 @@
   <java-symbol type="array" name="config_allowedSystemInstantAppSettings" />
   <java-symbol type="array" name="config_allowedSecureInstantAppSettings" />
 
+  <java-symbol type="dimen" name="notification_text_size_colorized" />
+  <java-symbol type="dimen" name="notification_title_text_size_colorized" />
+
   <java-symbol type="bool" name="config_handleVolumeKeysInWindowManager" />
   <java-symbol type="dimen" name="config_inCallNotificationVolume" />
   <java-symbol type="string" name="config_inCallNotificationSound" />
diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java
index c707240..a8d5164 100644
--- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java
+++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java
@@ -275,6 +275,21 @@
     }
 
     @Test
+    public void testStepLoop() {
+        openTuner();
+
+        for (int i = 0; i < 10; i++) {
+            Log.d(TAG, "step loop iteration " + (i + 1));
+
+            int ret = mRadioTuner.step(RadioTuner.DIRECTION_DOWN, true);
+            assertEquals(RadioManager.STATUS_OK, ret);
+            verify(mCallback, timeout(kTuneCallbackTimeoutMs)).onProgramInfoChanged(any());
+
+            resetCallback();
+        }
+    }
+
+    @Test
     public void testTuneAndGetPI() {
         openTuner();
 
diff --git a/core/tests/coretests/src/android/database/NewDatabasePerformanceTestSuite.java b/core/tests/coretests/src/android/database/NewDatabasePerformanceTestSuite.java
index c9db034..6156692 100644
--- a/core/tests/coretests/src/android/database/NewDatabasePerformanceTestSuite.java
+++ b/core/tests/coretests/src/android/database/NewDatabasePerformanceTestSuite.java
@@ -23,6 +23,7 @@
         TestSuite suite =
           new TestSuite(NewDatabasePerformanceTestSuite.class.getName());
 
+        suite.addTestSuite(NewDatabasePerformanceTests.CreateTable100.class);
         suite.addTestSuite(NewDatabasePerformanceTests.Insert100.class);
         suite.addTestSuite(NewDatabasePerformanceTests.InsertIndexed100.class);
         suite.addTestSuite(NewDatabasePerformanceTests.Select100.class);
diff --git a/core/tests/coretests/src/android/database/NewDatabasePerformanceTests.java b/core/tests/coretests/src/android/database/NewDatabasePerformanceTests.java
index f8d8e5e..75809c0 100644
--- a/core/tests/coretests/src/android/database/NewDatabasePerformanceTests.java
+++ b/core/tests/coretests/src/android/database/NewDatabasePerformanceTests.java
@@ -18,53 +18,96 @@
 
 import android.content.ContentValues;
 import android.database.sqlite.SQLiteDatabase;
+import android.os.SystemProperties;
 import android.test.PerformanceTestCase;
+import android.util.ArrayMap;
 import android.util.Log;
 
 import junit.framework.TestCase;
 
 import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.List;
+import java.util.Map;
 import java.util.Random;
 
 /**
- * Database Performance Tests
- * 
+ * Database Performance Tests.
+ *
+ * <p>Usage:
+ * <code>./frameworks/base/core/tests/coretests/src/android/database/run_newdb_perf_test.sh</code>
+ * <p>Test with WAL journaling enabled:
+ * <code>setprop debug.NewDatabasePerformanceTests.enable_wal 1</code>
  */
-
 public class NewDatabasePerformanceTests {
     private static final String TAG = "NewDatabasePerformanceTests";
 
-    // Edit this to change the test run times.  The original is 100.
-    private static final int SIZE_MULTIPLIER = 100;
+    private static final boolean DEBUG_ENABLE_WAL = SystemProperties
+            .getBoolean("debug.NewDatabasePerformanceTests.enable_wal", false);
+
+    private static final int DATASET_SIZE = 100; // Size of dataset to use for testing
+    private static final int FAST_OP_MULTIPLIER = 25;
+    private static final int FAST_OP_COUNT = FAST_OP_MULTIPLIER * DATASET_SIZE;
+
+    private static Long sInitialWriteBytes;
+
+    static {
+        sInitialWriteBytes = getIoStats().get("write_bytes");
+        if (DEBUG_ENABLE_WAL) {
+            Log.i(TAG, "Testing with WAL enabled");
+        }
+    }
 
     public static class PerformanceBase extends TestCase
-    implements PerformanceTestCase {
+            implements PerformanceTestCase {
         protected static final int CURRENT_DATABASE_VERSION = 42;
         protected SQLiteDatabase mDatabase;
         protected File mDatabaseFile;
         private long mSetupFinishedTime;
+        private Long mSetupWriteBytes;
 
         public void setUp() {
             long setupStarted = System.currentTimeMillis();
             mDatabaseFile = new File("/sdcard", "perf_database_test.db");
             if (mDatabaseFile.exists()) {
-                mDatabaseFile.delete();
+                SQLiteDatabase.deleteDatabase(mDatabaseFile);
             }
-            mDatabase =
-                    SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(),
-                            null);
-            assertTrue(mDatabase != null);
+            SQLiteDatabase.OpenParams.Builder params = new SQLiteDatabase.OpenParams.Builder();
+            params.addOpenFlags(SQLiteDatabase.CREATE_IF_NECESSARY);
+            if (DEBUG_ENABLE_WAL) {
+                params.addOpenFlags(SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING);
+            }
+            mDatabase = SQLiteDatabase.openDatabase(mDatabaseFile, params.build());
+            if (DEBUG_ENABLE_WAL) {
+                assertTrue("Cannot enable WAL", mDatabase.isWriteAheadLoggingEnabled());
+            }
             mDatabase.setVersion(CURRENT_DATABASE_VERSION);
+            mDatabase.beginTransactionNonExclusive();
+            prepareForTest();
+            mDatabase.setTransactionSuccessful();
+            mDatabase.endTransaction();
             mSetupFinishedTime = System.currentTimeMillis();
             Log.i(TAG, "Setup for " + getClass().getSimpleName() + " took "
                     + (mSetupFinishedTime - setupStarted) + " ms");
+            mSetupWriteBytes = getIoStats().get("write_bytes");
+        }
+
+        protected void prepareForTest() {
         }
 
         public void tearDown() {
             long duration = System.currentTimeMillis() - mSetupFinishedTime;
             Log.i(TAG, "Test " + getClass().getSimpleName() + " took " + duration + " ms");
             mDatabase.close();
-            mDatabaseFile.delete();
+            SQLiteDatabase.deleteDatabase(mDatabaseFile);
+            Long writeBytes = getIoStats().get("write_bytes");
+            if (writeBytes != null && sInitialWriteBytes != null) {
+                long testWriteBytes = writeBytes - mSetupWriteBytes;
+                long totalWriteBytes = (writeBytes - sInitialWriteBytes);
+                Log.i(TAG, "Test " + getClass().getSimpleName() + " write_bytes=" + testWriteBytes
+                        + ". Since tests started - totalWriteBytes=" + totalWriteBytes);
+            }
         }
 
         public boolean isPerformanceOnly() {
@@ -76,7 +119,7 @@
             return 0;
         }
 
-        public String numberName(int number) {
+        String numberName(int number) {
             String result = "";
 
             if (number >= 1000) {
@@ -106,36 +149,50 @@
 
             return result;
         }
+
+        void checkCursor(Cursor c) {
+            c.getColumnCount();
+            c.close();
+        }
+    }
+
+    /**
+     * Test CREATE SIZE tables with 1 row.
+     */
+    public static class CreateTable100 extends PerformanceBase {
+        public void testRun() {
+            for (int i = 0; i < DATASET_SIZE; i++) {
+                String t = "t" + i;
+                mDatabase.execSQL("CREATE TABLE " + t + "(a INTEGER, b INTEGER, c VARCHAR(100))");
+                mDatabase.execSQL("INSERT INTO " + t + " VALUES(" + i + "," + i + ",'"
+                        + numberName(i) + "')");
+            }
+        }
     }
 
     /**
      * Test 100 inserts.
      */
-
     public static class Insert100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-
-        private String[] statements = new String[SIZE];
+        private String[] mStatements = new String[DATASET_SIZE];
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
-                statements[i] =
+                mStatements[i] =
                         "INSERT INTO t1 VALUES(" + i + "," + r + ",'"
                                 + numberName(r) + "')";
             }
 
-            mDatabase
-            .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
         }
 
         public void testRun() {
-            for (int i = 0; i < SIZE; i++) {
-                mDatabase.execSQL(statements[i]);
+            for (int i = 0; i < DATASET_SIZE; i++) {
+                mDatabase.execSQL(mStatements[i]);
             }
         }
     }
@@ -145,30 +202,25 @@
      */
 
     public static class InsertIndexed100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-
-        private String[] statements = new String[SIZE];
+        private String[] mStatements = new String[DATASET_SIZE];
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
-                statements[i] =
-                        "INSERT INTO t1 VALUES(" + i + "," + r + ",'"
-                                + numberName(r) + "')";
+                mStatements[i] = "INSERT INTO t1 VALUES(" + i + "," + r + ",'"
+                        + numberName(r) + "')";
             }
 
-            mDatabase
-            .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
             mDatabase.execSQL("CREATE INDEX i1c ON t1(c)");
         }
 
         public void testRun() {
-            for (int i = 0; i < SIZE; i++) {
-                mDatabase.execSQL(statements[i]);
+            for (int i = 0; i < DATASET_SIZE; i++) {
+                mDatabase.execSQL(mStatements[i]);
             }
         }
     }
@@ -176,41 +228,35 @@
     /**
      * 100 SELECTs without an index
      */
-
     public static class Select100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-        private static final int REPEAT_COUNT = 10;
         private static final String[] COLUMNS = {"count(*)", "avg(b)"};
 
-        private String[] where = new String[SIZE];
+        private String[] mWhere = new String[DATASET_SIZE];
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
             mDatabase
             .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
             }
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int lower = i * 100;
                 int upper = (i + 10) * 100;
-                where[i] = "b >= " + lower + " AND b < " + upper;
+                mWhere[i] = "b >= " + lower + " AND b < " + upper;
             }
         }
 
         public void testRun() {
-            for (int iter = 0; iter < REPEAT_COUNT; iter++) {
-                for (int i = 0; i < SIZE; i++) {
-                    mDatabase
-                            .query("t1", COLUMNS, where[i], null, null, null, null);
-                }
+            for (int i = 0; i < FAST_OP_COUNT; i++) {
+                checkCursor(mDatabase
+                        .query("t1", COLUMNS, mWhere[i % DATASET_SIZE], null, null, null, null));
             }
         }
     }
@@ -219,37 +265,32 @@
      * 100 SELECTs on a string comparison
      */
     public static class SelectStringComparison100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-        private static final int REPEAT_COUNT = 10;
         private static final String[] COLUMNS = {"count(*)", "avg(b)"};
 
-        private String[] where = new String[SIZE];
+        private String[] mWhere = new String[DATASET_SIZE];
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
             mDatabase
             .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
             }
 
-            for (int i = 0; i < SIZE; i++) {
-                where[i] = "c LIKE '" + numberName(i) + "'";
+            for (int i = 0; i < DATASET_SIZE; i++) {
+                mWhere[i] = "c LIKE '" + numberName(i) + "'";
             }
         }
 
         public void testRun() {
-            for (int iter = 0; iter < REPEAT_COUNT; iter++) {
-                for (int i = 0; i < SIZE; i++) {
-                    mDatabase
-                            .query("t1", COLUMNS, where[i], null, null, null, null);
-                }
+            for (int i = 0; i < FAST_OP_COUNT; i++) {
+                checkCursor(mDatabase
+                        .query("t1", COLUMNS, mWhere[i % DATASET_SIZE], null, null, null, null));
             }
         }
     }
@@ -258,40 +299,35 @@
      * 100 SELECTs with an index
      */
     public static class SelectIndex100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-        private static final int REPEAT_COUNT = 10;
+        private static final int TABLE_SIZE = 100;
         private static final String[] COLUMNS = {"count(*)", "avg(b)"};
 
-        private String[] where = new String[SIZE];
+        private String[] mWhere = new String[TABLE_SIZE];
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
-            mDatabase
-            .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
             mDatabase.execSQL("CREATE INDEX i1b ON t1(b)");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < TABLE_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
             }
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < TABLE_SIZE; i++) {
                 int lower = i * 100;
                 int upper = (i + 10) * 100;
-                where[i] = "b >= " + lower + " AND b < " + upper;
+                mWhere[i] = "b >= " + lower + " AND b < " + upper;
             }
         }
 
         public void testRun() {
-            for (int iter = 0; iter < REPEAT_COUNT; iter++) {
-                for (int i = 0; i < SIZE; i++) {
-                    mDatabase
-                            .query("t1", COLUMNS, where[i], null, null, null, null);
-                }
+            for (int i = 0; i < FAST_OP_COUNT; i++) {
+                checkCursor(mDatabase
+                        .query("t1", COLUMNS, mWhere[i % TABLE_SIZE], null, null, null, null));
             }
         }
     }
@@ -300,27 +336,22 @@
      *  INNER JOIN without an index
      */
     public static class InnerJoin100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-        private static final int REPEAT_COUNT = 10;
         private static final String[] COLUMNS = {"t1.a"};
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
-            mDatabase
-            .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
-            mDatabase
-            .execSQL("CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100))");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
             }
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t2 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
@@ -328,9 +359,9 @@
         }
 
         public void testRun() {
-            for (int iter = 0; iter < REPEAT_COUNT; iter++) {
-                mDatabase.query("t1 INNER JOIN t2 ON t1.b = t2.b", COLUMNS, null,
-                        null, null, null, null);
+            for (int i = 0; i < FAST_OP_COUNT; i++) {
+                checkCursor(mDatabase.query("t1 INNER JOIN t2 ON t1.b = t2.b", COLUMNS, null,
+                        null, null, null, null));
             }
         }
     }
@@ -340,29 +371,24 @@
      */
 
     public static class InnerJoinOneSide100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-        private static final int REPEAT_COUNT = 10;
         private static final String[] COLUMNS = {"t1.a"};
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
-            mDatabase
-            .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
-            mDatabase
-            .execSQL("CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100))");
 
             mDatabase.execSQL("CREATE INDEX i1b ON t1(b)");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
             }
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t2 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
@@ -370,9 +396,9 @@
         }
 
         public void testRun() {
-            for (int iter = 0; iter < REPEAT_COUNT; iter++) {
-                mDatabase.query("t1 INNER JOIN t2 ON t1.b = t2.b", COLUMNS, null,
-                        null, null, null, null);
+            for (int i = 0; i < FAST_OP_COUNT; i++) {
+                checkCursor(mDatabase.query("t1 INNER JOIN t2 ON t1.b = t2.b", COLUMNS, null,
+                        null, null, null, null));
             }
         }
     }
@@ -381,29 +407,24 @@
      *  INNER JOIN without an index on one side
      */
     public static class InnerJoinNoIndex100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-        private static final int REPEAT_COUNT = 10;
         private static final String[] COLUMNS = {"t1.a"};
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
-            mDatabase
-            .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
-            mDatabase
-            .execSQL("CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100))");
 
             mDatabase.execSQL("CREATE INDEX i1b ON t1(b)");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
             }
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t2 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
@@ -411,9 +432,10 @@
         }
 
         public void testRun() {
-            for (int iter = 0; iter < REPEAT_COUNT; iter++) {
-                mDatabase.query("t1 INNER JOIN t2 ON t1.c = t2.c", COLUMNS, null,
-                        null, null, null, null);
+            for (int i = 0; i < FAST_OP_COUNT; i++) {
+                checkCursor(mDatabase
+                        .query("t1 INNER JOIN t2 ON t1.c = t2.c", COLUMNS, null, null, null, null,
+                                null));
             }
         }
     }
@@ -422,49 +444,44 @@
      *  100 SELECTs with subqueries. Subquery is using an index
      */
     public static class SelectSubQIndex100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-        private static final int REPEAT_COUNT = 10;
         private static final String[] COLUMNS = {"t1.a"};
 
-        private String[] where = new String[SIZE];
+        private String[] mWhere = new String[DATASET_SIZE];
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
-            mDatabase
-            .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
-            mDatabase
-            .execSQL("CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100))");
 
             mDatabase.execSQL("CREATE INDEX i2b ON t2(b)");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
             }
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t2 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
             }
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int lower = i * 100;
                 int upper = (i + 10) * 100;
-                where[i] =
+                mWhere[i] =
                         "t1.b IN (SELECT t2.b FROM t2 WHERE t2.b >= " + lower
                         + " AND t2.b < " + upper + ")";
             }
         }
 
         public void testRun() {
-            for (int i = 0; i < SIZE; i++) {
-                mDatabase
-                .query("t1", COLUMNS, where[i], null, null, null, null);
+            for (int i = 0; i < FAST_OP_COUNT; i++) {
+                checkCursor(mDatabase
+                        .query("t1", COLUMNS, mWhere[i % DATASET_SIZE], null, null, null, null));
             }
         }
     }
@@ -473,38 +490,32 @@
      *  100 SELECTs on string comparison with Index
      */
     public static class SelectIndexStringComparison100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-        private static final int REPEAT_COUNT = 10;
         private static final String[] COLUMNS = {"count(*)", "avg(b)"};
 
-        private String[] where = new String[SIZE];
+        private String[] mWhere = new String[DATASET_SIZE];
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
-            mDatabase
-            .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
             mDatabase.execSQL("CREATE INDEX i3c ON t1(c)");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
             }
 
-            for (int i = 0; i < SIZE; i++) {
-                where[i] = "c LIKE '" + numberName(i) + "'";
+            for (int i = 0; i < DATASET_SIZE; i++) {
+                mWhere[i] = "c LIKE '" + numberName(i) + "'";
             }
         }
 
         public void testRun() {
-            for (int iter = 0; iter < REPEAT_COUNT; iter++) {
-                for (int i = 0; i < SIZE; i++) {
-                    mDatabase
-                            .query("t1", COLUMNS, where[i], null, null, null, null);
-                }
+            for (int i = 0; i < FAST_OP_COUNT; i++) {
+                checkCursor(mDatabase
+                        .query("t1", COLUMNS, mWhere[i % DATASET_SIZE], null, null, null, null));
             }
         }
     }
@@ -513,19 +524,15 @@
      *  100 SELECTs on integer
      */
     public static class SelectInteger100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-        private static final int REPEAT_COUNT = 10;
         private static final String[] COLUMNS = {"b"};
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
-            mDatabase
-            .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
@@ -534,10 +541,8 @@
         }
 
         public void testRun() {
-            for (int iter = 0; iter < REPEAT_COUNT; iter++) {
-                for (int i = 0; i < SIZE; i++) {
-                    mDatabase.query("t1", COLUMNS, null, null, null, null, null);
-                }
+            for (int i = 0; i < FAST_OP_COUNT; i++) {
+                checkCursor(mDatabase.query("t1", COLUMNS, null, null, null, null, null));
             }
         }
     }
@@ -546,19 +551,16 @@
      *  100 SELECTs on String
      */
     public static class SelectString100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-        private static final int REPEAT_COUNT = 10;
         private static final String[] COLUMNS = {"c"};
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
             mDatabase
             .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
@@ -566,10 +568,8 @@
         }
 
         public void testRun() {
-            for (int iter = 0; iter < REPEAT_COUNT; iter++) {
-                for (int i = 0; i < SIZE; i++) {
-                    mDatabase.query("t1", COLUMNS, null, null, null, null, null);
-                }
+            for (int i = 0; i < FAST_OP_COUNT; i++) {
+                mDatabase.query("t1", COLUMNS, null, null, null, null, null);
             }
         }
     }
@@ -578,20 +578,17 @@
      *  100 SELECTs on integer with index
      */
     public static class SelectIntegerIndex100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-        private static final int REPEAT_COUNT = 10;
         private static final String[] COLUMNS = {"b"};
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
             mDatabase
             .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
             mDatabase.execSQL("CREATE INDEX i1b on t1(b)");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
@@ -600,10 +597,8 @@
         }
 
         public void testRun() {
-            for (int iter = 0; iter < REPEAT_COUNT; iter++) {
-                for (int i = 0; i < SIZE; i++) {
-                    mDatabase.query("t1", COLUMNS, null, null, null, null, null);
-                }
+            for (int i = 0; i < FAST_OP_COUNT; i++) {
+                mDatabase.query("t1", COLUMNS, null, null, null, null, null);
             }
         }
     }
@@ -612,20 +607,16 @@
      *  100 SELECTs on String with index
      */
     public static class SelectIndexString100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-        private static final int REPEAT_COUNT = 10;
         private static final String[] COLUMNS = {"c"};
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
-            mDatabase
-            .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
             mDatabase.execSQL("CREATE INDEX i1c ON t1(c)");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
@@ -633,10 +624,8 @@
         }
 
         public void testRun() {
-            for (int iter = 0; iter < REPEAT_COUNT; iter++) {
-                for (int i = 0; i < SIZE; i++) {
-                    mDatabase.query("t1", COLUMNS, null, null, null, null, null);
-                }
+            for (int i = 0; i < FAST_OP_COUNT; i++) {
+                checkCursor(mDatabase.query("t1", COLUMNS, null, null, null, null, null));
             }
         }
 
@@ -646,40 +635,33 @@
      *  100 SELECTs on String with starts with
      */
     public static class SelectStringStartsWith100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-        private static final int REPEAT_COUNT = 10;
         private static final String[] COLUMNS = {"c"};
-        private String[] where = new String[SIZE];
+        private String[] mWhere = new String[DATASET_SIZE];
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
-            mDatabase
-            .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
             mDatabase.execSQL("CREATE INDEX i1c ON t1(c)");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
             }
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
-                where[i] = "c LIKE '" + numberName(r).substring(0, 1) + "*'";
+                mWhere[i] = "c LIKE '" + numberName(r).substring(0, 1) + "*'";
 
             }
 
         }
 
         public void testRun() {
-            for (int iter = 0; iter < REPEAT_COUNT; iter++) {
-                for (int i = 0; i < SIZE; i++) {
-                    mDatabase
-                            .query("t1", COLUMNS, where[i], null, null, null, null);
-                }
+            for (int i = 0; i < FAST_OP_COUNT; i++) {
+                mDatabase.query("t1", COLUMNS, mWhere[i % DATASET_SIZE], null, null, null, null);
             }
         }
     }
@@ -688,18 +670,15 @@
      *  100 Deletes on an indexed table
      */
     public static class DeleteIndexed100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
-            mDatabase
-            .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
             mDatabase.execSQL("CREATE INDEX i3c ON t1(c)");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
@@ -708,7 +687,7 @@
         }
 
         public void testRun() {
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 mDatabase.delete("t1", null, null);
             }
         }
@@ -718,17 +697,13 @@
      *  100 Deletes
      */
     public static class Delete100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
-            mDatabase
-            .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
@@ -737,7 +712,7 @@
         }
 
         public void testRun() {
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 mDatabase.delete("t1", null, null);
             }
         }
@@ -747,33 +722,30 @@
      *  100 DELETE's without an index with where clause
      */
     public static class DeleteWhere100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-        private String[] where = new String[SIZE];
+        private String[] mWhere = new String[DATASET_SIZE];
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
-            mDatabase
-            .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
             }
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int lower = i * 100;
                 int upper = (i + 10) * 100;
-                where[i] = "b >= " + lower + " AND b < " + upper;
+                mWhere[i] = "b >= " + lower + " AND b < " + upper;
             }
         }
 
         public void testRun() {
-            for (int i = 0; i < SIZE; i++) {
-                mDatabase.delete("t1", where[i], null);
+            for (int i = 0; i < DATASET_SIZE; i++) {
+                mDatabase.delete("t1", mWhere[i], null);
             }
         }
     }
@@ -782,34 +754,31 @@
      * 100 DELETE's with an index with where clause
      */
     public static class DeleteIndexWhere100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-        private String[] where = new String[SIZE];
+        private String[] mWhere = new String[DATASET_SIZE];
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
-            mDatabase
-            .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
             mDatabase.execSQL("CREATE INDEX i1b ON t1(b)");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
             }
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int lower = i * 100;
                 int upper = (i + 10) * 100;
-                where[i] = "b >= " + lower + " AND b < " + upper;
+                mWhere[i] = "b >= " + lower + " AND b < " + upper;
             }
         }
 
         public void testRun() {
-            for (int i = 0; i < SIZE; i++) {
-                mDatabase.delete("t1", where[i], null);
+            for (int i = 0; i < DATASET_SIZE; i++) {
+                mDatabase.delete("t1", mWhere[i], null);
             }
         }
     }
@@ -818,30 +787,26 @@
      * 100 update's with an index with where clause
      */
     public static class UpdateIndexWhere100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-        private String[] where = new String[SIZE];
-        ContentValues[] mValues = new ContentValues[SIZE];
+        private String[] mWhere = new String[DATASET_SIZE];
+        ContentValues[] mValues = new ContentValues[DATASET_SIZE];
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
-            mDatabase
-            .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
             mDatabase.execSQL("CREATE INDEX i1b ON t1(b)");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
             }
 
-            for (int i = 0; i < SIZE; i++) {
-
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int lower = i * 100;
                 int upper = (i + 10) * 100;
-                where[i] = "b >= " + lower + " AND b < " + upper;
+                mWhere[i] = "b >= " + lower + " AND b < " + upper;
                 ContentValues b = new ContentValues(1);
                 b.put("b", upper);
                 mValues[i] = b;
@@ -850,8 +815,8 @@
         }
 
         public void testRun() {
-            for (int i = 0; i < SIZE; i++) {
-                mDatabase.update("t1", mValues[i], where[i], null);
+            for (int i = 0; i < DATASET_SIZE; i++) {
+                mDatabase.update("t1", mValues[i], mWhere[i], null);
             }
         }
     }
@@ -860,29 +825,26 @@
      * 100 update's without an index with where clause
      */
     public static class UpdateWhere100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-        private String[] where = new String[SIZE];
-        ContentValues[] mValues = new ContentValues[SIZE];
+        private String[] mWhere = new String[DATASET_SIZE];
+        ContentValues[] mValues = new ContentValues[DATASET_SIZE];
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
-            mDatabase
-            .execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100))");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t1 VALUES(" + i + "," + r + ",'"
                         + numberName(r) + "')");
             }
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
 
                 int lower = i * 100;
                 int upper = (i + 10) * 100;
-                where[i] = "b >= " + lower + " AND b < " + upper;
+                mWhere[i] = "b >= " + lower + " AND b < " + upper;
                 ContentValues b = new ContentValues(1);
                 b.put("b", upper);
                 mValues[i] = b;
@@ -890,8 +852,8 @@
         }
 
         public void testRun() {
-            for (int i = 0; i < SIZE; i++) {
-                mDatabase.update("t1", mValues[i], where[i], null);
+            for (int i = 0; i < DATASET_SIZE; i++) {
+                mDatabase.update("t1", mValues[i], mWhere[i], null);
             }
         }
     }
@@ -900,36 +862,31 @@
      * 100 selects for a String - contains 'e'
      */
     public static class SelectStringContains100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-        private static final int REPEAT_COUNT = 10;
         private static final String[] COLUMNS = {"t3.a"};
-        private String[] where = new String[SIZE];
+        private String[] mWhere = new String[DATASET_SIZE];
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
-            mDatabase
-            .execSQL("CREATE TABLE t3(a VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t3(a VARCHAR(100))");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t3 VALUES('"
                         + numberName(r) + "')");
             }
 
-            for (int i = 0; i < SIZE; i++) {
-                where[i] = "a LIKE '*e*'";
+            for (int i = 0; i < DATASET_SIZE; i++) {
+                mWhere[i] = "a LIKE '*e*'";
 
             }
         }
 
         public void testRun() {
-            for (int iter = 0; iter < REPEAT_COUNT; iter++) {
-                for (int i = 0; i < SIZE; i++) {
-                    mDatabase.query("t3", COLUMNS, where[i], null, null, null, null);
-                }
+            for (int i = 0; i < FAST_OP_COUNT; i++) {
+                checkCursor(mDatabase
+                        .query("t3", COLUMNS, mWhere[i % DATASET_SIZE], null, null, null, null));
             }
         }
     }
@@ -938,37 +895,32 @@
      * 100 selects for a String - contains 'e'-indexed table
      */
     public static class SelectStringIndexedContains100 extends PerformanceBase {
-        private static final int SIZE = SIZE_MULTIPLIER;
-        private static final int REPEAT_COUNT = 10;
         private static final String[] COLUMNS = {"t3.a"};
-        private String[] where = new String[SIZE];
+        private String[] mWhere = new String[DATASET_SIZE];
 
         @Override
-        public void setUp() {
-            super.setUp();
+        protected void prepareForTest() {
             Random random = new Random(42);
 
-            mDatabase
-            .execSQL("CREATE TABLE t3(a VARCHAR(100))");
+            mDatabase.execSQL("CREATE TABLE t3(a VARCHAR(100))");
             mDatabase.execSQL("CREATE INDEX i3a ON t3(a)");
 
-            for (int i = 0; i < SIZE; i++) {
+            for (int i = 0; i < DATASET_SIZE; i++) {
                 int r = random.nextInt(100000);
                 mDatabase.execSQL("INSERT INTO t3 VALUES('"
                         + numberName(r) + "')");
             }
 
-            for (int i = 0; i < SIZE; i++) {
-                where[i] = "a LIKE '*e*'";
+            for (int i = 0; i < DATASET_SIZE; i++) {
+                mWhere[i] = "a LIKE '*e*'";
 
             }
         }
 
         public void testRun() {
-            for (int iter = 0; iter < REPEAT_COUNT; iter++) {
-                for (int i = 0; i < SIZE; i++) {
-                    mDatabase.query("t3", COLUMNS, where[i], null, null, null, null);
-                }
+            for (int i = 0; i < FAST_OP_COUNT; i++) {
+                checkCursor(mDatabase
+                        .query("t3", COLUMNS, mWhere[i % DATASET_SIZE], null, null, null, null));
             }
         }
     }
@@ -982,4 +934,31 @@
     static final String[] TENS =
         {"", "ten", "twenty", "thirty", "forty", "fifty", "sixty",
         "seventy", "eighty", "ninety"};
+
+    static Map<String, Long> getIoStats() {
+        String ioStat = "/proc/self/io";
+        Map<String, Long> results = new ArrayMap<>();
+        try {
+            List<String> lines = Files.readAllLines(new File(ioStat).toPath());
+            for (String line : lines) {
+                line = line.trim();
+                String[] split = line.split(":");
+                if (split.length == 2) {
+                    try {
+                        String key = split[0].trim();
+                        Long value = Long.valueOf(split[1].trim());
+                        results.put(key, value);
+                    } catch (NumberFormatException e) {
+                        Log.e(TAG, "Cannot parse number from " + line);
+                    }
+                } else if (line.isEmpty()) {
+                    Log.e(TAG, "Cannot parse line " + line);
+                }
+            }
+        } catch (IOException e) {
+            Log.e(TAG, "Can't read: " + ioStat, e);
+        }
+        return results;
+    }
+
 }
diff --git a/core/tests/coretests/src/android/database/process_newdb_perf_test_logs.py b/core/tests/coretests/src/android/database/process_newdb_perf_test_logs.py
index 1faeceb..27b20c3 100644
--- a/core/tests/coretests/src/android/database/process_newdb_perf_test_logs.py
+++ b/core/tests/coretests/src/android/database/process_newdb_perf_test_logs.py
@@ -25,7 +25,16 @@
         all_lines = f.readlines()
     timings = {}
     running_sum = 0
+    # If WAL was enabled for the test
+    wal_enabled = False
+    # Number of bytes which test process caused to be sent to the storage layer.
+    # Reported as max value across all runs.
+    max_write_bytes = 0
     for line in all_lines:
+        if "NewDatabasePerformanceTests: Testing with WAL enabled" in line:
+            wal_enabled = True
+            continue
+
         regex = r"NewDatabasePerformanceTests: Test (\w+) took (\d+) ms"
         matches = re.search(regex, line)
         if matches:
@@ -35,16 +44,31 @@
                 timings[test_name] = []
             timings[test_name].append(duration)
             running_sum += duration
+            continue
+
         if ("TestRunner: run finished:" in line) and (running_sum > 0):
-            test_name = '*** TOTAL ALL TESTS (ms) ***'
+            test_name = ('*** TOTAL ALL TESTS [WAL] (ms) ***' if wal_enabled
+                         else '*** TOTAL ALL TESTS (ms) ***')
             if not test_name in timings:
                 timings[test_name] = []
             timings[test_name].append(running_sum)
             running_sum=0
+            continue
+
+        # Determine max from all reported totalWriteBytes
+        regex = r"Test .* totalWriteBytes=(\d+)"
+        matches = re.search(regex, line)
+        if matches:
+            max_write_bytes = max(max_write_bytes, int(matches.group(1)))
+            continue
 
     for k in sorted(timings):
         timings_ar = timings[k]
         print "%s: %s avg: %s" % (k, timings_ar, sum(timings_ar) / float(len(timings_ar)) )
 
+
+    print "\nAdditional stats: "
+    print "    max write_bytes: %d" % max_write_bytes
+
 if __name__ == '__main__':
     main()
diff --git a/core/tests/coretests/src/android/database/run_newdb_perf_test.sh b/core/tests/coretests/src/android/database/run_newdb_perf_test.sh
index 10a62e6..c5b2c97 100755
--- a/core/tests/coretests/src/android/database/run_newdb_perf_test.sh
+++ b/core/tests/coretests/src/android/database/run_newdb_perf_test.sh
@@ -17,8 +17,11 @@
 adb install -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
 adb logcat -c
 
-echo "Running benchmark 5 times"
-for i in {1..5}
+# by default run 5 times
+RUN_N=${1:-5}
+echo "Running benchmark $RUN_N times"
+
+for (( i=0; i<$RUN_N; i++ ))
 do
     adb  shell am instrument -e class 'android.database.NewDatabasePerformanceTestSuite' -w 'com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner'
 done
diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
index d5f6321..9686dd9 100644
--- a/core/tests/coretests/src/android/net/LinkPropertiesTest.java
+++ b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
@@ -24,10 +24,15 @@
 import android.system.OsConstants;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.test.suitebuilder.annotation.Suppress;
+import android.util.ArraySet;
+
 import junit.framework.TestCase;
 
 import java.net.InetAddress;
-import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
 
 
 public class LinkPropertiesTest extends TestCase {
@@ -678,4 +683,76 @@
         stacked.addRoute(new RouteInfo((IpPrefix) null, stackedAddress));
         assertTrue(v6lp.isReachable(DNS1));
     }
+
+    @SmallTest
+    public void testLinkPropertiesEnsureDirectlyConnectedRoutes() {
+        // IPv4 case: no route added initially
+        LinkProperties rmnet0 = new LinkProperties();
+        rmnet0.setInterfaceName("rmnet0");
+        rmnet0.addLinkAddress(new LinkAddress("10.0.0.2/8"));
+        RouteInfo directRoute0 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null,
+                rmnet0.getInterfaceName());
+
+        // Since no routes is added explicitly, getAllRoutes() should return empty.
+        assertTrue(rmnet0.getAllRoutes().isEmpty());
+        rmnet0.ensureDirectlyConnectedRoutes();
+        // ensureDirectlyConnectedRoutes() should have added the missing local route.
+        assertEqualRoutes(Collections.singletonList(directRoute0), rmnet0.getAllRoutes());
+
+        // IPv4 case: both direct and default routes added initially
+        LinkProperties rmnet1 = new LinkProperties();
+        rmnet1.setInterfaceName("rmnet1");
+        rmnet1.addLinkAddress(new LinkAddress("10.0.0.3/8"));
+        RouteInfo defaultRoute1 = new RouteInfo((IpPrefix) null,
+                NetworkUtils.numericToInetAddress("10.0.0.1"), rmnet1.getInterfaceName());
+        RouteInfo directRoute1 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null,
+                rmnet1.getInterfaceName());
+        rmnet1.addRoute(defaultRoute1);
+        rmnet1.addRoute(directRoute1);
+
+        // Check added routes
+        assertEqualRoutes(Arrays.asList(defaultRoute1, directRoute1), rmnet1.getAllRoutes());
+        // ensureDirectlyConnectedRoutes() shouldn't change the routes since direct connected
+        // route is already part of the configuration.
+        rmnet1.ensureDirectlyConnectedRoutes();
+        assertEqualRoutes(Arrays.asList(defaultRoute1, directRoute1), rmnet1.getAllRoutes());
+
+        // IPv6 case: only default routes added initially
+        LinkProperties rmnet2 = new LinkProperties();
+        rmnet2.setInterfaceName("rmnet2");
+        rmnet2.addLinkAddress(new LinkAddress("fe80::cafe/64"));
+        rmnet2.addLinkAddress(new LinkAddress("2001:db8::2/64"));
+        RouteInfo defaultRoute2 = new RouteInfo((IpPrefix) null,
+                NetworkUtils.numericToInetAddress("2001:db8::1"), rmnet2.getInterfaceName());
+        RouteInfo directRoute2 = new RouteInfo(new IpPrefix("2001:db8::/64"), null,
+                rmnet2.getInterfaceName());
+        RouteInfo linkLocalRoute2 = new RouteInfo(new IpPrefix("fe80::/64"), null,
+                rmnet2.getInterfaceName());
+        rmnet2.addRoute(defaultRoute2);
+
+        assertEqualRoutes(Arrays.asList(defaultRoute2), rmnet2.getAllRoutes());
+        rmnet2.ensureDirectlyConnectedRoutes();
+        assertEqualRoutes(Arrays.asList(defaultRoute2, directRoute2, linkLocalRoute2),
+                rmnet2.getAllRoutes());
+
+        // Corner case: no interface name
+        LinkProperties rmnet3 = new LinkProperties();
+        rmnet3.addLinkAddress(new LinkAddress("192.168.0.2/24"));
+        RouteInfo directRoute3 = new RouteInfo(new IpPrefix("192.168.0.0/24"), null,
+                rmnet3.getInterfaceName());
+
+        assertTrue(rmnet3.getAllRoutes().isEmpty());
+        rmnet3.ensureDirectlyConnectedRoutes();
+        assertEqualRoutes(Collections.singletonList(directRoute3), rmnet3.getAllRoutes());
+
+    }
+
+    private void assertEqualRoutes(Collection<RouteInfo> expected, Collection<RouteInfo> actual) {
+        Set<RouteInfo> expectedSet = new ArraySet<>(expected);
+        Set<RouteInfo> actualSet = new ArraySet<>(actual);
+        // Duplicated entries in actual routes are considered failures
+        assertEquals(actual.size(), actualSet.size());
+
+        assertEquals(expectedSet, actualSet);
+    }
 }
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 3b71e42..43e762d3 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -328,6 +328,7 @@
                     Settings.Global.SMS_SHORT_CODE_RULE,
                     Settings.Global.SMS_SHORT_CODES_UPDATE_CONTENT_URL,
                     Settings.Global.SMS_SHORT_CODES_UPDATE_METADATA_URL,
+                    Settings.Global.SPEED_LABEL_CACHE_EVICTION_AGE_MILLIS,
                     Settings.Global.STORAGE_BENCHMARK_INTERVAL,
                     Settings.Global.STORAGE_SETTINGS_CLOBBER_THRESHOLD,
                     Settings.Global.SYNC_MAX_RETRY_DELAY_IN_SECONDS,
diff --git a/core/tests/coretests/src/android/text/format/FormatterTest.java b/core/tests/coretests/src/android/text/format/FormatterTest.java
index ff75c29..24e3646 100644
--- a/core/tests/coretests/src/android/text/format/FormatterTest.java
+++ b/core/tests/coretests/src/android/text/format/FormatterTest.java
@@ -17,10 +17,12 @@
 package android.text.format;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.icu.util.MeasureUnit;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -32,6 +34,8 @@
 import org.junit.runner.RunWith;
 
 import java.util.Locale;
+import java.util.Set;
+
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
@@ -205,4 +209,24 @@
 
         Locale.setDefault(locale);
     }
+
+    /**
+     * Verifies that Formatter doesn't "leak" the locally defined petabyte unit into ICU via the
+     * {@link MeasureUnit} registry. This test can fail for two reasons:
+     * 1. we regressed and started leaking again. In this case the code needs to be fixed.
+     * 2. ICU started supporting petabyte as a unit, in which case change one needs to revert this
+     * change (I494fb59a3b3742f35cbdf6b8705817f404a2c6b0), remove Formatter.PETABYTE and replace any
+     * usages of that field with just MeasureUnit.PETABYTE.
+     */
+    // http://b/65632959
+    @Test
+    public void doesNotLeakPetabyte() {
+        // Ensure that the Formatter class is loaded when we call .getAvailable().
+        Formatter.formatFileSize(mContext, Long.MAX_VALUE);
+        Set<MeasureUnit> digitalUnits = MeasureUnit.getAvailable("digital");
+        for (MeasureUnit unit : digitalUnits) {
+            // This assert can fail if we don't leak PETABYTE, but ICU has added it, see #2 above.
+            assertNotEquals("petabyte", unit.getSubtype());
+        }
+    }
 }
diff --git a/data/sounds/AudioPackageGo.mk b/data/sounds/AudioPackageGo.mk
index 3756d30..ae742df 100644
--- a/data/sounds/AudioPackageGo.mk
+++ b/data/sounds/AudioPackageGo.mk
@@ -40,3 +40,9 @@
     $(LOCAL_PATH)/Alarm_Beep_03.ogg:system/media/audio/alarms/Alarm_Beep_03.ogg \
     $(LOCAL_PATH)/alarms/ogg/Helium.ogg:system/media/audio/alarms/Helium.ogg \
     $(LOCAL_PATH)/alarms/ogg/Oxygen.ogg:system/media/audio/alarms/Oxygen.ogg \
+    $(LOCAL_PATH)/effects/ogg/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \
+    $(LOCAL_PATH)/effects/ogg/KeypressStandard.ogg:system/media/audio/ui/KeypressStandard.ogg \
+    $(LOCAL_PATH)/effects/ogg/KeypressSpacebar.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
+    $(LOCAL_PATH)/effects/ogg/KeypressDelete.ogg:system/media/audio/ui/KeypressDelete.ogg \
+    $(LOCAL_PATH)/effects/ogg/KeypressInvalid.ogg:system/media/audio/ui/KeypressInvalid.ogg \
+    $(LOCAL_PATH)/effects/ogg/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
diff --git a/data/sounds/AudioTv.mk b/data/sounds/AudioTv.mk
new file mode 100644
index 0000000..ee37cb9
--- /dev/null
+++ b/data/sounds/AudioTv.mk
@@ -0,0 +1,125 @@
+# Copyright 2017 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.
+
+LOCAL_PATH := frameworks/base/data/sounds
+
+PRODUCT_COPY_FILES += \
+    $(LOCAL_PATH)/Alarm_Beep_01.ogg:system/media/audio/alarms/Alarm_Beep_01.ogg \
+    $(LOCAL_PATH)/Alarm_Beep_02.ogg:system/media/audio/alarms/Alarm_Beep_02.ogg \
+    $(LOCAL_PATH)/Alarm_Beep_03.ogg:system/media/audio/alarms/Alarm_Beep_03.ogg \
+    $(LOCAL_PATH)/Alarm_Buzzer.ogg:system/media/audio/alarms/Alarm_Buzzer.ogg \
+    $(LOCAL_PATH)/Alarm_Classic.ogg:system/media/audio/alarms/Alarm_Classic.ogg \
+    $(LOCAL_PATH)/Alarm_Rooster_02.ogg:system/media/audio/alarms/Alarm_Rooster_02.ogg \
+    $(LOCAL_PATH)/alarms/ogg/Argon.ogg:system/media/audio/alarms/Argon.ogg \
+    $(LOCAL_PATH)/alarms/ogg/Barium.ogg:system/media/audio/alarms/Barium.ogg \
+    $(LOCAL_PATH)/alarms/ogg/Carbon.ogg:system/media/audio/alarms/Carbon.ogg \
+    $(LOCAL_PATH)/alarms/ogg/Cesium.ogg:system/media/audio/alarms/Cesium.ogg \
+    $(LOCAL_PATH)/alarms/ogg/Fermium.ogg:system/media/audio/alarms/Fermium.ogg \
+    $(LOCAL_PATH)/alarms/ogg/Hassium.ogg:system/media/audio/alarms/Hassium.ogg \
+    $(LOCAL_PATH)/alarms/ogg/Helium.ogg:system/media/audio/alarms/Helium.ogg \
+    $(LOCAL_PATH)/alarms/ogg/Krypton.ogg:system/media/audio/alarms/Krypton.ogg \
+    $(LOCAL_PATH)/alarms/ogg/Neon.ogg:system/media/audio/alarms/Neon.ogg \
+    $(LOCAL_PATH)/alarms/ogg/Neptunium.ogg:system/media/audio/alarms/Neptunium.ogg \
+    $(LOCAL_PATH)/alarms/ogg/Nobelium.ogg:system/media/audio/alarms/Nobelium.ogg \
+    $(LOCAL_PATH)/alarms/ogg/Osmium.ogg:system/media/audio/alarms/Osmium.ogg \
+    $(LOCAL_PATH)/alarms/ogg/Oxygen.ogg:system/media/audio/alarms/Oxygen.ogg \
+    $(LOCAL_PATH)/alarms/ogg/Platinum.ogg:system/media/audio/alarms/Platinum.ogg \
+    $(LOCAL_PATH)/alarms/ogg/Plutonium.ogg:system/media/audio/alarms/Plutonium.ogg \
+    $(LOCAL_PATH)/alarms/ogg/Promethium.ogg:system/media/audio/alarms/Promethium.ogg \
+    $(LOCAL_PATH)/alarms/ogg/Scandium.ogg:system/media/audio/alarms/Scandium.ogg \
+    $(LOCAL_PATH)/effects/ogg/camera_click_48k.ogg:system/media/audio/ui/camera_click.ogg \
+    $(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
+    $(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
+    $(LOCAL_PATH)/effects/ogg/Effect_Tick_48k.ogg:system/media/audio/ui/Effect_Tick.ogg \
+    $(LOCAL_PATH)/effects/ogg/KeypressDelete_120_48k.ogg:system/media/audio/ui/KeypressDelete.ogg \
+    $(LOCAL_PATH)/effects/ogg/KeypressInvalid_120_48k.ogg:system/media/audio/ui/KeypressInvalid.ogg \
+    $(LOCAL_PATH)/effects/ogg/KeypressReturn_120_48k.ogg:system/media/audio/ui/KeypressReturn.ogg \
+    $(LOCAL_PATH)/effects/ogg/KeypressSpacebar_120_48k.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
+    $(LOCAL_PATH)/effects/ogg/KeypressStandard_120_48k.ogg:system/media/audio/ui/KeypressStandard.ogg \
+    $(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
+    $(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+    $(LOCAL_PATH)/effects/ogg/Trusted_48k.ogg:system/media/audio/ui/Trusted.ogg \
+    $(LOCAL_PATH)/effects/ogg/Undock.ogg:system/media/audio/ui/Undock.ogg \
+    $(LOCAL_PATH)/effects/ogg/Unlock.ogg:system/media/audio/ui/Unlock.ogg \
+    $(LOCAL_PATH)/effects/ogg/VideoRecord_48k.ogg:system/media/audio/ui/VideoRecord.ogg \
+    $(LOCAL_PATH)/effects/ogg/VideoStop_48k.ogg:system/media/audio/ui/VideoStop.ogg \
+    $(LOCAL_PATH)/effects/ogg/WirelessChargingStarted.ogg:system/media/audio/ui/WirelessChargingStarted.ogg \
+    $(LOCAL_PATH)/F1_MissedCall.ogg:system/media/audio/notifications/F1_MissedCall.ogg \
+    $(LOCAL_PATH)/F1_New_MMS.ogg:system/media/audio/notifications/F1_New_MMS.ogg \
+    $(LOCAL_PATH)/F1_New_SMS.ogg:system/media/audio/notifications/F1_New_SMS.ogg \
+    $(LOCAL_PATH)/notifications/Aldebaran.ogg:system/media/audio/notifications/Aldebaran.ogg \
+    $(LOCAL_PATH)/notifications/Altair.ogg:system/media/audio/notifications/Altair.ogg \
+    $(LOCAL_PATH)/notifications/Antares.ogg:system/media/audio/notifications/Antares.ogg \
+    $(LOCAL_PATH)/notifications/arcturus.ogg:system/media/audio/notifications/arcturus.ogg \
+    $(LOCAL_PATH)/notifications/Beat_Box_Android.ogg:system/media/audio/notifications/Beat_Box_Android.ogg \
+    $(LOCAL_PATH)/notifications/Betelgeuse.ogg:system/media/audio/notifications/Betelgeuse.ogg \
+    $(LOCAL_PATH)/notifications/Canopus.ogg:system/media/audio/notifications/Canopus.ogg \
+    $(LOCAL_PATH)/notifications/Castor.ogg:system/media/audio/notifications/Castor.ogg \
+    $(LOCAL_PATH)/notifications/Cricket.ogg:system/media/audio/notifications/Cricket.ogg \
+    $(LOCAL_PATH)/notifications/Deneb.ogg:system/media/audio/notifications/Deneb.ogg \
+    $(LOCAL_PATH)/notifications/Doink.ogg:system/media/audio/notifications/Doink.ogg \
+    $(LOCAL_PATH)/notifications/Drip.ogg:system/media/audio/notifications/Drip.ogg \
+    $(LOCAL_PATH)/notifications/Electra.ogg:system/media/audio/notifications/Electra.ogg \
+    $(LOCAL_PATH)/notifications/Fomalhaut.ogg:system/media/audio/notifications/Fomalhaut.ogg \
+    $(LOCAL_PATH)/notifications/Heaven.ogg:system/media/audio/notifications/Heaven.ogg \
+    $(LOCAL_PATH)/notifications/Merope.ogg:system/media/audio/notifications/Merope.ogg \
+    $(LOCAL_PATH)/notifications/moonbeam.ogg:system/media/audio/notifications/moonbeam.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Adara.ogg:system/media/audio/notifications/Adara.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Alya.ogg:system/media/audio/notifications/Alya.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Antimony.ogg:system/media/audio/notifications/Antimony.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Arcturus.ogg:system/media/audio/notifications/Arcturus.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Argon.ogg:system/media/audio/notifications/Argon.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Bellatrix.ogg:system/media/audio/notifications/Bellatrix.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Beryllium.ogg:system/media/audio/notifications/Beryllium.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Capella.ogg:system/media/audio/notifications/Capella.ogg \
+    $(LOCAL_PATH)/notifications/ogg/CetiAlpha.ogg:system/media/audio/notifications/CetiAlpha.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Cobalt.ogg:system/media/audio/notifications/Cobalt.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Fluorine.ogg:system/media/audio/notifications/Fluorine.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Gallium.ogg:system/media/audio/notifications/Gallium.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Helium.ogg:system/media/audio/notifications/Helium.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Hojus.ogg:system/media/audio/notifications/Hojus.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Iridium.ogg:system/media/audio/notifications/Iridium.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Krypton.ogg:system/media/audio/notifications/Krypton.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Lalande.ogg:system/media/audio/notifications/Lalande.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Mira.ogg:system/media/audio/notifications/Mira.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Palladium.ogg:system/media/audio/notifications/Palladium.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Polaris.ogg:system/media/audio/notifications/Polaris.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Pollux.ogg:system/media/audio/notifications/Pollux.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Procyon.ogg:system/media/audio/notifications/Procyon.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Proxima.ogg:system/media/audio/notifications/Proxima.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Radon.ogg:system/media/audio/notifications/Radon.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Rubidium.ogg:system/media/audio/notifications/Rubidium.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Selenium.ogg:system/media/audio/notifications/Selenium.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Shaula.ogg:system/media/audio/notifications/Shaula.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Spica.ogg:system/media/audio/notifications/Spica.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Strontium.ogg:system/media/audio/notifications/Strontium.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Syrma.ogg:system/media/audio/notifications/Syrma.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Talitha.ogg:system/media/audio/notifications/Talitha.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Tejat.ogg:system/media/audio/notifications/Tejat.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Thallium.ogg:system/media/audio/notifications/Thallium.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Upsilon.ogg:system/media/audio/notifications/Upsilon.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Vega.ogg:system/media/audio/notifications/Vega.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Xenon.ogg:system/media/audio/notifications/Xenon.ogg \
+    $(LOCAL_PATH)/notifications/ogg/Zirconium.ogg:system/media/audio/notifications/Zirconium.ogg \
+    $(LOCAL_PATH)/notifications/pixiedust.ogg:system/media/audio/notifications/pixiedust.ogg \
+    $(LOCAL_PATH)/notifications/pizzicato.ogg:system/media/audio/notifications/pizzicato.ogg \
+    $(LOCAL_PATH)/notifications/Plastic_Pipe.ogg:system/media/audio/notifications/Plastic_Pipe.ogg \
+    $(LOCAL_PATH)/notifications/regulus.ogg:system/media/audio/notifications/regulus.ogg \
+    $(LOCAL_PATH)/notifications/sirius.ogg:system/media/audio/notifications/sirius.ogg \
+    $(LOCAL_PATH)/notifications/Sirrah.ogg:system/media/audio/notifications/Sirrah.ogg \
+    $(LOCAL_PATH)/notifications/SpaceSeed.ogg:system/media/audio/notifications/SpaceSeed.ogg \
+    $(LOCAL_PATH)/notifications/TaDa.ogg:system/media/audio/notifications/TaDa.ogg \
+    $(LOCAL_PATH)/notifications/Tinkerbell.ogg:system/media/audio/notifications/Tinkerbell.ogg \
+    $(LOCAL_PATH)/notifications/tweeters.ogg:system/media/audio/notifications/tweeters.ogg \
+    $(LOCAL_PATH)/notifications/vega.ogg:system/media/audio/notifications/vega.ogg
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 3b272c8..ffb39e3 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -433,10 +433,15 @@
         static void validate(Options opts) {
             if (opts == null) return;
 
-            if (opts.inMutable && opts.inPreferredConfig == Bitmap.Config.HARDWARE) {
+            if (opts.inBitmap != null && opts.inBitmap.getConfig() == Bitmap.Config.HARDWARE) {
                 throw new IllegalArgumentException("Bitmaps with Config.HARWARE are always immutable");
             }
 
+            if (opts.inMutable && opts.inPreferredConfig == Bitmap.Config.HARDWARE) {
+                throw new IllegalArgumentException("Bitmaps with Config.HARDWARE cannot be " +
+                        "decoded into - they are immutable");
+            }
+
             if (opts.inPreferredColorSpace != null) {
                 if (!(opts.inPreferredColorSpace instanceof ColorSpace.Rgb)) {
                     throw new IllegalArgumentException("The destination color space must use the " +
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index ccf9de0..7e959a8 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -754,6 +754,8 @@
                 // None of the key's SIDs can ever be authenticated
                 return new KeyPermanentlyInvalidatedException();
             }
+            case UNINITIALIZED:
+                return new KeyPermanentlyInvalidatedException();
             default:
                 return new InvalidKeyException("Keystore operation failed", e);
         }
diff --git a/legacy-test/Android.mk b/legacy-test/Android.mk
index ef2950b..0e6b31e 100644
--- a/legacy-test/Android.mk
+++ b/legacy-test/Android.mk
@@ -94,11 +94,10 @@
 
 LOCAL_SOURCE_FILES_ALL_GENERATED := true
 
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
 # Make sure to run droiddoc first to generate the stub source files.
-$(full_classes_compiled_jar) : $(legacy_test_api_gen_stamp)
-$(full_classes_jack) : $(legacy_test_api_gen_stamp)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(legacy_test_api_gen_stamp)
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
 
 # Archive a copy of the classes.jar in SDK build.
 $(call dist-for-goals,sdk win_sdk,$(full_classes_jar):legacy.test.stubs.jar)
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index aa6d2f3..4a5b2c7 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -162,8 +162,8 @@
     void addRenderNode(RenderNode* node, bool placeFront);
     void removeRenderNode(RenderNode* node);
 
-    void setContentDrawBounds(int left, int top, int right, int bottom) {
-        mContentDrawBounds.set(left, top, right, bottom);
+    void setContentDrawBounds(const Rect& bounds) {
+        mContentDrawBounds = bounds;
     }
 
     RenderState& getRenderState() {
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 7d641d3..a097272 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -32,6 +32,7 @@
 DrawFrameTask::DrawFrameTask()
         : mRenderThread(nullptr)
         , mContext(nullptr)
+        , mContentDrawBounds(0, 0, 0, 0)
         , mSyncResult(SyncResult::OK) {
 }
 
@@ -123,6 +124,7 @@
         mLayers[i]->apply();
     }
     mLayers.clear();
+    mContext->setContentDrawBounds(mContentDrawBounds);
     mContext->prepareTree(info, mFrameInfo, mSyncQueued, mTargetNode);
 
     // This is after the prepareTree so that any pending operations
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index fb48062..83ecb98 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -61,6 +61,9 @@
     virtual ~DrawFrameTask();
 
     void setContext(RenderThread* thread, CanvasContext* context, RenderNode* targetNode);
+    void setContentDrawBounds(int left, int top, int right, int bottom) {
+        mContentDrawBounds.set(left, top, right, bottom);
+    }
 
     void pushLayerUpdate(DeferredLayerUpdater* layer);
     void removeLayerUpdate(DeferredLayerUpdater* layer);
@@ -82,6 +85,7 @@
     RenderThread* mRenderThread;
     CanvasContext* mContext;
     RenderNode* mTargetNode = nullptr;
+    Rect mContentDrawBounds;
 
     /*********************************************
      *  Single frame data
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 7fe966d..9048bd1 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -551,20 +551,8 @@
     staticPostAndWait(task);
 }
 
-CREATE_BRIDGE5(setContentDrawBounds, CanvasContext* context, int left, int top,
-        int right, int bottom) {
-    args->context->setContentDrawBounds(args->left, args->top, args->right, args->bottom);
-    return nullptr;
-}
-
 void RenderProxy::setContentDrawBounds(int left, int top, int right, int bottom) {
-    SETUP_TASK(setContentDrawBounds);
-    args->context = mContext;
-    args->left = left;
-    args->top = top;
-    args->right = right;
-    args->bottom = bottom;
-    staticPostAndWait(task);
+    mDrawFrameTask.setContentDrawBounds(left, top, right, bottom);
 }
 
 CREATE_BRIDGE1(serializeDisplayListTree, CanvasContext* context) {
diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp
index 3a77195..afb1193 100644
--- a/libs/hwui/service/GraphicsStatsService.cpp
+++ b/libs/hwui/service/GraphicsStatsService.cpp
@@ -40,7 +40,7 @@
 
 constexpr int sHistogramSize = ProfileData::HistogramSize();
 
-static void mergeProfileDataIntoProto(service::GraphicsStatsProto* proto,
+static bool mergeProfileDataIntoProto(service::GraphicsStatsProto* proto,
         const std::string& package, int versionCode, int64_t startTime, int64_t endTime,
         const ProfileData* data);
 static void dumpAsTextToFd(service::GraphicsStatsProto* proto, int outFd);
@@ -159,7 +159,7 @@
     return success;
 }
 
-void mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::string& package,
+bool mergeProfileDataIntoProto(service::GraphicsStatsProto* proto, const std::string& package,
         int versionCode, int64_t startTime, int64_t endTime, const ProfileData* data) {
     if (proto->stats_start() == 0 || proto->stats_start() > startTime) {
         proto->set_stats_start(startTime);
@@ -188,23 +188,31 @@
         proto->mutable_histogram()->Reserve(sHistogramSize);
         creatingHistogram = true;
     } else if (proto->histogram_size() != sHistogramSize) {
-        LOG_ALWAYS_FATAL("Histogram size mismatch, proto is %d expected %d",
+        ALOGE("Histogram size mismatch, proto is %d expected %d",
                 proto->histogram_size(), sHistogramSize);
+        return false;
     }
     int index = 0;
+    bool hitMergeError = false;
     data->histogramForEach([&](ProfileData::HistogramEntry entry) {
+        if (hitMergeError) return;
+
         service::GraphicsStatsHistogramBucketProto* bucket;
         if (creatingHistogram) {
             bucket = proto->add_histogram();
             bucket->set_render_millis(entry.renderTimeMs);
         } else {
             bucket = proto->mutable_histogram(index);
-            LOG_ALWAYS_FATAL_IF(bucket->render_millis() != static_cast<int32_t>(entry.renderTimeMs),
-                    "Frame time mistmatch %d vs. %u", bucket->render_millis(), entry.renderTimeMs);
+            if (bucket->render_millis() != static_cast<int32_t>(entry.renderTimeMs)) {
+                ALOGW("Frame time mistmatch %d vs. %u", bucket->render_millis(), entry.renderTimeMs);
+                hitMergeError = true;
+                return;
+            }
         }
         bucket->set_frame_count(bucket->frame_count() + entry.frameCount);
         index++;
     });
+    return !hitMergeError;
 }
 
 static int32_t findPercentile(service::GraphicsStatsProto* proto, int percentile) {
@@ -221,9 +229,11 @@
 
 void dumpAsTextToFd(service::GraphicsStatsProto* proto, int fd) {
     // This isn't a full validation, just enough that we can deref at will
-    LOG_ALWAYS_FATAL_IF(proto->package_name().empty()
-            || !proto->has_summary(), "package_name() '%s' summary %d",
-            proto->package_name().c_str(), proto->has_summary());
+    if (proto->package_name().empty() || !proto->has_summary()) {
+        ALOGW("Skipping dump, invalid package_name() '%s' or summary %d",
+                proto->package_name().c_str(), proto->has_summary());
+        return;
+    }
     dprintf(fd, "\nPackage: %s", proto->package_name().c_str());
     dprintf(fd, "\nVersion: %d", proto->version_code());
     dprintf(fd, "\nStats since: %lldns", proto->stats_start());
@@ -254,14 +264,20 @@
     if (!parseFromFile(path, &statsProto)) {
         statsProto.Clear();
     }
-    mergeProfileDataIntoProto(&statsProto, package, versionCode, startTime, endTime, data);
+    if (!mergeProfileDataIntoProto(&statsProto, package, versionCode, startTime, endTime, data)) {
+        return;
+    }
     // Although we might not have read any data from the file, merging the existing data
     // should always fully-initialize the proto
-    LOG_ALWAYS_FATAL_IF(!statsProto.IsInitialized(), "%s",
-            statsProto.InitializationErrorString().c_str());
-    LOG_ALWAYS_FATAL_IF(statsProto.package_name().empty()
-            || !statsProto.has_summary(), "package_name() '%s' summary %d",
-            statsProto.package_name().c_str(), statsProto.has_summary());
+    if (!statsProto.IsInitialized()) {
+        ALOGE("proto initialization error %s", statsProto.InitializationErrorString().c_str());
+        return;
+    }
+    if (statsProto.package_name().empty() || !statsProto.has_summary()) {
+        ALOGE("missing package_name() '%s' summary %d",
+                statsProto.package_name().c_str(), statsProto.has_summary());
+        return;
+    }
     int outFd = open(path.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0660);
     if (outFd <= 0) {
         int err = errno;
@@ -312,8 +328,9 @@
     if (!path.empty() && !parseFromFile(path, &statsProto)) {
         statsProto.Clear();
     }
-    if (data) {
-        mergeProfileDataIntoProto(&statsProto, package, versionCode, startTime, endTime, data);
+    if (data && !mergeProfileDataIntoProto(
+            &statsProto, package, versionCode, startTime, endTime, data)) {
+        return;
     }
     if (!statsProto.IsInitialized()) {
         ALOGW("Failed to load profile data from path '%s' and data %p",
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index eea4628..3df1706 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3058,7 +3058,11 @@
 
     private final IPlaybackConfigDispatcher mPlayCb = new IPlaybackConfigDispatcher.Stub() {
         @Override
-        public void dispatchPlaybackConfigChange(List<AudioPlaybackConfiguration> configs) {
+        public void dispatchPlaybackConfigChange(List<AudioPlaybackConfiguration> configs,
+                boolean flush) {
+            if (flush) {
+                Binder.flushPendingCommands();
+            }
             synchronized(mPlaybackCallbackLock) {
                 if (mPlaybackCallbackList != null) {
                     for (int i=0 ; i < mPlaybackCallbackList.size() ; i++) {
diff --git a/media/java/android/media/AudioPlaybackConfiguration.java b/media/java/android/media/AudioPlaybackConfiguration.java
index 14bc555..8a36f91 100644
--- a/media/java/android/media/AudioPlaybackConfiguration.java
+++ b/media/java/android/media/AudioPlaybackConfiguration.java
@@ -212,8 +212,10 @@
      * @hide
      */
     public void init() {
-        if (mIPlayerShell != null) {
-            mIPlayerShell.monitorDeath();
+        synchronized (this) {
+            if (mIPlayerShell != null) {
+                mIPlayerShell.monitorDeath();
+            }
         }
     }
 
@@ -322,7 +324,11 @@
      */
     @SystemApi
     public PlayerProxy getPlayerProxy() {
-        return mIPlayerShell == null ? null : new PlayerProxy(this);
+        final IPlayerShell ips;
+        synchronized (this) {
+            ips = mIPlayerShell;
+        }
+        return ips == null ? null : new PlayerProxy(this);
     }
 
     /**
@@ -330,7 +336,11 @@
      * @return the IPlayer interface for the associated player
      */
     IPlayer getIPlayer() {
-        return mIPlayerShell == null ? null : mIPlayerShell.getIPlayer();
+        final IPlayerShell ips;
+        synchronized (this) {
+            ips = mIPlayerShell;
+        }
+        return ips == null ? null : ips.getIPlayer();
     }
 
     /**
@@ -351,10 +361,14 @@
      * @return true if the state changed, false otherwise
      */
     public boolean handleStateEvent(int event) {
-        final boolean changed = (mPlayerState != event);
-        mPlayerState = event;
-        if ((event == PLAYER_STATE_RELEASED) && (mIPlayerShell != null)) {
-            mIPlayerShell.release();
+        final boolean changed;
+        synchronized (this) {
+            changed = (mPlayerState != event);
+            mPlayerState = event;
+            if (changed && (event == PLAYER_STATE_RELEASED) && (mIPlayerShell != null)) {
+                mIPlayerShell.release();
+                mIPlayerShell = null;
+            }
         }
         return changed;
     }
@@ -447,7 +461,11 @@
         dest.writeInt(mClientPid);
         dest.writeInt(mPlayerState);
         mPlayerAttr.writeToParcel(dest, 0);
-        dest.writeStrongInterface(mIPlayerShell == null ? null : mIPlayerShell.getIPlayer());
+        final IPlayerShell ips;
+        synchronized (this) {
+            ips = mIPlayerShell;
+        }
+        dest.writeStrongInterface(ips == null ? null : ips.getIPlayer());
     }
 
     private AudioPlaybackConfiguration(Parcel in) {
@@ -479,14 +497,17 @@
     static final class IPlayerShell implements IBinder.DeathRecipient {
 
         final AudioPlaybackConfiguration mMonitor; // never null
-        private IPlayer mIPlayer;
+        private volatile IPlayer mIPlayer;
 
         IPlayerShell(@NonNull AudioPlaybackConfiguration monitor, @NonNull IPlayer iplayer) {
             mMonitor = monitor;
             mIPlayer = iplayer;
         }
 
-        void monitorDeath() {
+        synchronized void monitorDeath() {
+            if (mIPlayer == null) {
+                return;
+            }
             try {
                 mIPlayer.asBinder().linkToDeath(this, 0);
             } catch (RemoteException e) {
@@ -509,8 +530,13 @@
             } else if (DEBUG) { Log.i(TAG, "IPlayerShell binderDied"); }
         }
 
-        void release() {
+        synchronized void release() {
+            if (mIPlayer == null) {
+                return;
+            }
             mIPlayer.asBinder().unlinkToDeath(this, 0);
+            mIPlayer = null;
+            Binder.flushPendingCommands();
         }
     }
 
@@ -532,7 +558,7 @@
             case PLAYER_TYPE_HW_SOURCE: return "hardware source";
             case PLAYER_TYPE_EXTERNAL_PROXY: return "external proxy";
             default:
-                return "unknown player type - FIXME";
+                return "unknown player type " + type + " - FIXME";
         }
     }
 
diff --git a/media/java/android/media/IPlaybackConfigDispatcher.aidl b/media/java/android/media/IPlaybackConfigDispatcher.aidl
index 3cb5216..150ff26 100644
--- a/media/java/android/media/IPlaybackConfigDispatcher.aidl
+++ b/media/java/android/media/IPlaybackConfigDispatcher.aidl
@@ -25,6 +25,6 @@
  */
 oneway interface IPlaybackConfigDispatcher {
 
-    void dispatchPlaybackConfigChange(in List<AudioPlaybackConfiguration> configs);
+    void dispatchPlaybackConfigChange(in List<AudioPlaybackConfiguration> configs, in boolean flush);
 
 }
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index f85925d..f41e33f 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -2749,8 +2749,8 @@
                 mQualityRange = Utils
                         .parseIntRange(info.getString("quality-range"), mQualityRange);
             }
-            if (info.containsKey("feature-bitrate-control")) {
-                for (String mode: info.getString("feature-bitrate-control").split(",")) {
+            if (info.containsKey("feature-bitrate-modes")) {
+                for (String mode: info.getString("feature-bitrate-modes").split(",")) {
                     mBitControl |= parseBitrateMode(mode);
                 }
             }
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
index 832b297..91e57ee 100644
--- a/media/java/android/media/MediaMuxer.java
+++ b/media/java/android/media/MediaMuxer.java
@@ -70,7 +70,7 @@
  <p>
   Per-frame metadata is useful in carrying extra information that correlated with video or audio to
   facilitate offline processing, e.g. gyro signals from the sensor could help video stabilization when
-  doing offline processing. Metaadata track is only supported in MP4 container. When adding a new
+  doing offline processing. Metadata track is only supported in MP4 container. When adding a new
   metadata track, track's mime format must start with prefix "application/", e.g. "applicaton/gyro".
   Metadata's format/layout will be defined by the application. Writing metadata is nearly the same as
   writing video/audio data except that the data will not be from mediacodec. Application just needs
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 2d008c7..022198b 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -137,7 +137,7 @@
     mLooper->start(
             false,      // runOnCallingThread
             true,       // canCallJava
-            PRIORITY_FOREGROUND);
+            ANDROID_PRIORITY_VIDEO);
 
     if (nameIsType) {
         mCodec = MediaCodec::CreateByType(mLooper, name, encoder, &mInitStatus);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index fcb861c..cf5882f 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -271,7 +271,7 @@
          * @see android.hardware.camera2.ICameraDeviceCallbacks#onRepeatingRequestError()
          */
         @Override
-        public void onRepeatingRequestError(long lastFrameNumber) {
+        public void onRepeatingRequestError(long lastFrameNumber, int repeatingRequestId) {
             // TODO Auto-generated method stub
         }
     }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index 476f016..e628b68 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -161,7 +161,7 @@
          * @see android.hardware.camera2.ICameraDeviceCallbacks#onRepeatingRequestError()
          */
         @Override
-        public void onRepeatingRequestError(long lastFrameNumber) {
+        public void onRepeatingRequestError(long lastFrameNumber, int repeatingRequestId) {
             // TODO Auto-generated method stub
         }
     }
diff --git a/packages/BackupRestoreConfirmation/res/values-bn/strings.xml b/packages/BackupRestoreConfirmation/res/values-bn/strings.xml
index 2b69d5b..afc8c3e 100644
--- a/packages/BackupRestoreConfirmation/res/values-bn/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-bn/strings.xml
@@ -20,13 +20,13 @@
     <string name="restore_confirm_title" msgid="5469365809567486602">"সম্পূর্ণ পুনরুদ্ধার"</string>
     <string name="backup_confirm_text" msgid="1878021282758896593">"একটি সংযুক্ত ডেস্কটপ কম্পিউটার থেকে সমস্ত ডেটার সম্পূর্ণ ব্যাকআপ নেওয়ার অনুরোধ করা হয়েছে৷ আপনি কি এটি করার অনুমতি দিতে চান?\n\nযদি আপনি নিজের থেকে এই ব্যাকআপ নেওয়ার অনুরোধ না করে থাকেন, তবে এটি প্রক্রিয়াটিতে অনুমতি প্রদান করবেন না৷"</string>
     <string name="allow_backup_button_label" msgid="4217228747769644068">"আমার ডেটার ব্যাকআপ রাখুন"</string>
-    <string name="deny_backup_button_label" msgid="6009119115581097708">"ব্যাক আপ করবেন না"</string>
+    <string name="deny_backup_button_label" msgid="6009119115581097708">"ব্যাক-আপ করবেন না"</string>
     <string name="restore_confirm_text" msgid="7499866728030461776">"একটি সংযুক্ত ডেস্কটপ কম্পিউটার থেকে সমস্ত ডেটার সম্পূর্ণ ব্যাকআপ নেওয়ার অনুরোধ করা হয়েছে৷ আপনি কি এটি করার অনুমতি দিতে চান?\n\nযদি আপনি নিজের থেকে এই ব্যাকআপ নেওয়ার অনুরোধ না করে থাকেন, তবে এই প্রক্রিয়াটিতে অনুমতি প্রদান করবেন না৷ এটি বর্তমানে ডিভাইসটিতে থাকা সমস্ত ডেটাকে প্রতিস্থাপন করবে!"</string>
     <string name="allow_restore_button_label" msgid="3081286752277127827">"আমার ডেটা পুনরুদ্ধার করুন"</string>
     <string name="deny_restore_button_label" msgid="1724367334453104378">"পুনরুদ্ধার করবেন না"</string>
     <string name="current_password_text" msgid="8268189555578298067">"দয়া করে নিচে আপনার বর্তমান ব্যাকআপের পাসওয়ার্ড দিন:"</string>
     <string name="device_encryption_restore_text" msgid="1570864916855208992">"দয়া করে নিচে আপনার ডিভাইসের এনক্রিপশান পাসওয়ার্ড লিখুন৷"</string>
-    <string name="device_encryption_backup_text" msgid="5866590762672844664">"দয়া করে নিচে আপানার ডিভাইসের এনক্রিপশান পাসওয়ার্ড লিখুন৷ এছাড়াও ব্যাকআপ সংরক্ষণাগার এনক্রিপ্ট করতে এটি ব্যবহার করা হবে৷"</string>
+    <string name="device_encryption_backup_text" msgid="5866590762672844664">"অনুগ্রহ করে নিচে আপানার ডিভাইসের এনক্রিপশান পাসওয়ার্ড লিখুন৷ এছাড়াও ব্যাক-আপ আর্কাইভ এনক্রিপ্ট করতে এটি ব্যবহার করা হবে৷"</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"সম্পূর্ণ ব্যাকআপ ডেটা এনক্রিপ্ট করতে দয়া করে একটি পাসওয়ার্ড লিখুন৷ যদি এটি খালি রেখে দেওয়া হয় তবে আপনার বর্তমান ব্যাকআপ পাসওয়ার্ডটি ব্যবহার করা হবে:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"আপনি যদি সম্পূর্ণ ব্যাকআপ ডেটা এনক্রিপ্ট করতে চান তাহলে নিচে একটি পাসওয়ার্ড লিখুন:"</string>
     <string name="backup_enc_password_required" msgid="7889652203371654149">"আপনার ডিভাইস এনক্রিপ্ট হয়ে থাকার কারণে আপনার ব্যাকআপকে এনক্রিপ্ট করতে হবে। দয়া করে নিচে একটি পাসওয়ার্ড দিন:"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-mr/strings.xml b/packages/BackupRestoreConfirmation/res/values-mr/strings.xml
index ea3b2f0..3ee60ca 100644
--- a/packages/BackupRestoreConfirmation/res/values-mr/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-mr/strings.xml
@@ -25,11 +25,11 @@
     <string name="allow_restore_button_label" msgid="3081286752277127827">"माझा डेटा पुनर्संचयित करा"</string>
     <string name="deny_restore_button_label" msgid="1724367334453104378">"पुनर्संचयित करू नका"</string>
     <string name="current_password_text" msgid="8268189555578298067">"कृपया आपला वर्तमान बॅकअप संकेतशब्‍द खाली प्रविष्‍ट करा:"</string>
-    <string name="device_encryption_restore_text" msgid="1570864916855208992">"कृपया तुमचे डीव्हाइस एंक्रिप्शन पासवर्ड खाली एंटर करा."</string>
-    <string name="device_encryption_backup_text" msgid="5866590762672844664">"कृपया तुमचे डीव्हाइस एंक्रिप्शन पासवर्ड खाली एंटर करा. हा बॅकअप संग्रह एंक्रिप्ट करण्‍यासाठी देखील वापरला जाईल."</string>
+    <string name="device_encryption_restore_text" msgid="1570864916855208992">"कृपया तुमचे डिव्हाइस एंक्रिप्शन पासवर्ड खाली एंटर करा."</string>
+    <string name="device_encryption_backup_text" msgid="5866590762672844664">"कृपया तुमचे डिव्हाइस एंक्रिप्शन पासवर्ड खाली एंटर करा. हा बॅकअप संग्रह एंक्रिप्ट करण्‍यासाठी देखील वापरला जाईल."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"कृपया पूर्ण बॅकअप डेटा एंक्रिप्ट करण्‍यासाठी वापरण्याकरिता पासवर्ड एंटर करा. हे रिक्त सोडल्‍यास, आपला वर्तमान बॅकअप पासवर्ड वापरला जाईल:"</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"तुम्ही पूर्ण बॅकअप डेटा एंक्रिप्ट करू इच्‍छित असल्‍यास, खालील पासवर्ड एंटर करा:"</string>
-    <string name="backup_enc_password_required" msgid="7889652203371654149">"तुमचे डीव्हाइस एंक्रिप्ट केले असल्यामुळे, तुम्हाला तुमचा बॅक अप एंक्रिप्ट करणे आवश्यक आहे. कृपया खाली एक पासवर्ड एंटर करा:"</string>
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"तुमचे डिव्हाइस एंक्रिप्ट केले असल्यामुळे, तुम्हाला तुमचा बॅक अप एंक्रिप्ट करणे आवश्यक आहे. कृपया खाली एक पासवर्ड एंटर करा:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"पुनर्स्टोअर केलेला डेटा एंक्रिप्ट केला असल्‍यास, कृपया पासवर्ड खाली एंटर करा:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"बॅकअप सुरू होत आहे..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"बॅकअप समाप्त झाले"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-pa/strings.xml b/packages/BackupRestoreConfirmation/res/values-pa/strings.xml
index dd3b580..72513ba 100644
--- a/packages/BackupRestoreConfirmation/res/values-pa/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-pa/strings.xml
@@ -16,23 +16,23 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="backup_confirm_title" msgid="827563724209303345">"ਪੂਰਾ ਬੈਕਅਪ"</string>
+    <string name="backup_confirm_title" msgid="827563724209303345">"ਪੂਰਾ ਬੈਕਅੱਪ"</string>
     <string name="restore_confirm_title" msgid="5469365809567486602">"ਪੂਰਾ ਰੀਸਟੋਰ"</string>
-    <string name="backup_confirm_text" msgid="1878021282758896593">"ਇੱਕ ਕਨੈਕਟ ਕੀਤੇ ਡੈਸਕਟੌਪ ਕੰਪਿਊਟਰ ਦੇ ਸਾਰੇ ਡੈਟਾ ਦੇ ਇੱਕ ਪੁੂਰੇ ਬੈਕਅਪ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਗਈ ਹੈ। ਕੀ ਤੁਸੀਂ ਅਜਿਹਾ ਹੋਣ ਦੀ ਆਗਿਆ ਦੇਣਾ ਚਾਹੁੰਦੇ ਹੋ?\n\nਜੇਕਰ ਤੁਸੀਂ ਖੁਦ ਬੈਕਅਪ ਦੀ ਬੇਨਤੀ ਨਹੀਂ ਕੀਤੀ ਸੀ, ਤਾਂ ਓਪਰੇਸ਼ਨ ਜਾਰੀ ਰੱਖਣ ਦੀ ਆਗਿਆ ਨਾ ਦਿਓ।"</string>
-    <string name="allow_backup_button_label" msgid="4217228747769644068">"ਮੇਰਾ ਡੈਟਾ ਬੈਕ ਅਪ ਕਰੋ"</string>
-    <string name="deny_backup_button_label" msgid="6009119115581097708">"ਬੈਕ ਅਪ ਨਾ ਕਰੋ"</string>
-    <string name="restore_confirm_text" msgid="7499866728030461776">"ਇੱਕ ਕਨੈਕਟ ਕੀਤੇ ਡੈਸਕਟਾਪ ਕੰਪਿਊਟਰ ਦੇ ਸਾਰੇ ਡਾਟਾ ਦੇ ਇੱਕ ਪੁੂਰੇ ਰੀਸਟੋਰ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਗਈ ਹੈ। ਕੀ ਤੁਸੀਂ ਅਜਿਹਾ ਹੋਣ ਦੀ ਆਗਿਆ ਦੇਣਾ ਚਾਹੁੰਦੇ ਹੋ?\n\nਜੇਕਰ ਤੁਸੀਂ ਖੁਦ ਰੀਸਟੋਰ ਦੀ ਬੇਨਤੀ ਨਹੀਂ ਕੀਤੀ ਸੀ, ਤਾਂ ਓਪਰੇਸ਼ਨ ਜਾਰੀ ਰੱਖਣ ਦੀ ਆਗਿਆ ਨਾ ਦਿਓ। ਇਹ ਡੀਵਾਈਸ ਤੇ ਇਸ ਵੇਲੇ ਮੌਜੂਦ ਕਿਸੇ ਵੀ ਡਾਟਾ ਨੂੰ ਬਦਲ ਦੇਵੇਗਾ!"</string>
-    <string name="allow_restore_button_label" msgid="3081286752277127827">"ਮੇਰਾ ਡੈਟਾ ਰੀਸਟੋਰ ਕਰੋ"</string>
+    <string name="backup_confirm_text" msgid="1878021282758896593">"ਇੱਕ ਕਨੈਕਟ ਕੀਤੇ ਡੈਸਕਟਾਪ ਕੰਪਿਊਟਰ ਦੇ ਸਾਰੇ ਡਾਟਾ ਦੇ ਇੱਕ ਪੁੂਰੇ ਬੈਕਅੱਪ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਗਈ ਹੈ। ਕੀ ਤੁਸੀਂ ਅਜਿਹਾ ਹੋਣ ਦੀ ਆਗਿਆ ਦੇਣਾ ਚਾਹੁੰਦੇ ਹੋ?\n\nਜੇਕਰ ਤੁਸੀਂ ਖੁਦ ਬੈਕਅੱਪ ਦੀ ਬੇਨਤੀ ਨਹੀਂ ਕੀਤੀ ਸੀ, ਤਾਂ ਓਪਰੇਸ਼ਨ ਜਾਰੀ ਰੱਖਣ ਦੀ ਆਗਿਆ ਨਾ ਦਿਓ।"</string>
+    <string name="allow_backup_button_label" msgid="4217228747769644068">"ਮੇਰਾ ਡਾਟਾ ਬੈਕ ਅੱਪ ਲਓ"</string>
+    <string name="deny_backup_button_label" msgid="6009119115581097708">"ਬੈਕ ਅੱਪ ਨਾ ਕਰੋ"</string>
+    <string name="restore_confirm_text" msgid="7499866728030461776">"ਇੱਕ ਕਨੈਕਟ ਕੀਤੇ ਡੈਸਕਟਾਪ ਕੰਪਿਊਟਰ ਦੇ ਸਾਰੇ ਡਾਟਾ ਦੇ ਇੱਕ ਪੁੂਰੇ ਰੀਸਟੋਰ ਦੀ ਬੇਨਤੀ ਕੀਤੀ ਗਈ ਹੈ। ਕੀ ਤੁਸੀਂ ਅਜਿਹਾ ਹੋਣ ਦੀ ਆਗਿਆ ਦੇਣਾ ਚਾਹੁੰਦੇ ਹੋ?\n\nਜੇਕਰ ਤੁਸੀਂ ਖੁਦ ਰੀਸਟੋਰ ਦੀ ਬੇਨਤੀ ਨਹੀਂ ਕੀਤੀ ਸੀ, ਤਾਂ ਓਪਰੇਸ਼ਨ ਜਾਰੀ ਰੱਖਣ ਦੀ ਆਗਿਆ ਨਾ ਦਿਓ। ਇਹ ਡੀਵਾਈਸ \'ਤੇ ਇਸ ਵੇਲੇ ਮੌਜੂਦ ਕਿਸੇ ਵੀ ਡਾਟਾ ਨੂੰ ਬਦਲ ਦੇਵੇਗਾ!"</string>
+    <string name="allow_restore_button_label" msgid="3081286752277127827">"ਮੇਰਾ  ਡਾਟਾ  ਰੀਸਟੋਰ ਕਰੋ"</string>
     <string name="deny_restore_button_label" msgid="1724367334453104378">"ਰੀਸਟੋਰ ਨਾ ਕਰੋ"</string>
-    <string name="current_password_text" msgid="8268189555578298067">"ਕਿਰਪਾ ਕਰਕੇ ਹੇਠਾਂ ਆਪਣਾ ਮੌਜੂਦਾ ਬੈਕਅਪ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ:"</string>
+    <string name="current_password_text" msgid="8268189555578298067">"ਕਿਰਪਾ ਕਰਕੇ ਹੇਠਾਂ ਆਪਣਾ ਮੌਜੂਦਾ ਬੈਕਅੱਪ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ:"</string>
     <string name="device_encryption_restore_text" msgid="1570864916855208992">"ਕਿਰਪਾ ਕਰਕੇ ਹੇਠਾਂ ਆਪਣਾ ਡੀਵਾਈਸ ਇਨਕ੍ਰਿਪਸ਼ਨ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ।"</string>
-    <string name="device_encryption_backup_text" msgid="5866590762672844664">"ਕਿਰਪਾ ਕਰਕੇ ਹੇਠਾਂ ਆਪਣਾ ਡੀਵਾਈਸ ਇਨਕ੍ਰਿਪਸ਼ਨ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ। ਇਹ ਬੈਕਅੱਪ ਆਰਕਾਈਵ ਇਨਕ੍ਰਿਪਟ ਕਰਨ ਲਈ ਵੀ ਵਰਤਿਆ ਜਾਏਗਾ।"</string>
-    <string name="backup_enc_password_text" msgid="4981585714795233099">"ਕਿਰਪਾ ਕਰਕੇ ਪੂਰਾ ਬੈਕਅਪ ਡੈਟਾ ਇਨਕ੍ਰਿਪਟ ਕਰਨ ਦੀ ਵਰਤੋਂ ਲਈ ਇੱਕ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ। ਜੇਕਰ ਇਸਨੂੰ ਖਾਲੀ ਛੱਡਿਆ ਜਾਂਦਾ ਹੈ, ਤਾਂ ਤੁਹਾਡਾ ਵਰਤਮਾਨ ਬੈਕਅਪ ਪਾਸਵਰਡ ਵਰਤਿਆ ਜਾਏਗਾ:"</string>
-    <string name="backup_enc_password_optional" msgid="1350137345907579306">"ਜੇਕਰ ਤੁਸੀਂ ਪੂਰਾ ਬੈਕਅਪ ਡੈਟਾ ਇਨਕ੍ਰਿਪਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ, ਤਾਂ ਹੇਠਾਂ ਇੱਕ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ:"</string>
-    <string name="backup_enc_password_required" msgid="7889652203371654149">"ਕਿਉਂਕਿ ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਇਨਕ੍ਰਿਪਟਿਡ ਹੈ, ਇਸਲਈ ਤੁਹਾਡੇ ਤੋਂ ਆਪਣਾ ਬੈਕਅੱਪ ਇਨਕ੍ਰਿਪਟ ਕਰਨ ਦੀ ਮੰਗ ਕੀਤੀ ਜਾਂਦੀ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਹੇਠਾਂ ਇੱਕ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ:"</string>
-    <string name="restore_enc_password_text" msgid="6140898525580710823">"ਜੇਕਰ ਰੀਸਟੋਰ ਡੈਟਾ ਇਨਕ੍ਰਿਪਟ ਕੀਤਾ ਗਿਆ ਹੈ, ਤਾਂ ਹੇਠਾਂ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ:"</string>
-    <string name="toast_backup_started" msgid="550354281452756121">"ਬੈਕਅਪ ਚਾਲੂ ਕਰ ਰਿਹਾ ਹੈ..."</string>
-    <string name="toast_backup_ended" msgid="3818080769548726424">"ਬੈਕਅਪ ਪੂਰਾ ਹੋਇਆ"</string>
+    <string name="device_encryption_backup_text" msgid="5866590762672844664">"ਕਿਰਪਾ ਕਰਕੇ ਹੇਠਾਂ ਆਪਣਾ ਡੀਵਾਈਸ ਇਨਕ੍ਰਿਪਸ਼ਨ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ। ਇਹ ਬੈਕਅੱਪ ਪੁਰਾਲੇਖ ਇਨਕ੍ਰਿਪਟ ਕਰਨ ਲਈ ਵੀ ਵਰਤਿਆ ਜਾਏਗਾ।"</string>
+    <string name="backup_enc_password_text" msgid="4981585714795233099">"ਕਿਰਪਾ ਕਰਕੇ ਪੂਰਾ ਬੈਕਅੱਪ ਡਾਟਾ ਇਨਕ੍ਰਿਪਟ ਕਰਨ ਦੀ ਵਰਤੋਂ ਲਈ ਇੱਕ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ। ਜੇਕਰ ਇਸਨੂੰ ਖਾਲੀ ਛੱਡਿਆ ਜਾਂਦਾ ਹੈ, ਤਾਂ ਤੁਹਾਡਾ ਵਰਤਮਾਨ ਬੈਕਅੱਪ ਪਾਸਵਰਡ ਵਰਤਿਆ ਜਾਏਗਾ:"</string>
+    <string name="backup_enc_password_optional" msgid="1350137345907579306">"ਜੇਕਰ ਤੁਸੀਂ ਪੂਰਾ ਬੈਕਅੱਪ ਡਾਟਾ ਇਨਕ੍ਰਿਪਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ, ਤਾਂ ਹੇਠਾਂ ਇੱਕ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ:"</string>
+    <string name="backup_enc_password_required" msgid="7889652203371654149">"ਕਿਉਂਕਿ ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਇਨਕ੍ਰਿਪਟਡ ਹੈ, ਇਸਲਈ ਤੁਹਾਡੇ ਤੋਂ ਆਪਣਾ ਬੈਕਅੱਪ ਇਨਕ੍ਰਿਪਟ ਕਰਨ ਦੀ ਮੰਗ ਕੀਤੀ ਜਾਂਦੀ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਹੇਠਾਂ ਇੱਕ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ:"</string>
+    <string name="restore_enc_password_text" msgid="6140898525580710823">"ਜੇਕਰ ਰੀਸਟੋਰ ਡਾਟਾ ਇਨਕ੍ਰਿਪਟ ਕੀਤਾ ਗਿਆ ਹੈ, ਤਾਂ ਹੇਠਾਂ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ:"</string>
+    <string name="toast_backup_started" msgid="550354281452756121">"ਬੈਕਅੱਪ ਚਾਲੂ ਕਰ ਰਿਹਾ ਹੈ..."</string>
+    <string name="toast_backup_ended" msgid="3818080769548726424">"ਬੈਕਅੱਪ ਪੂਰਾ ਹੋਇਆ"</string>
     <string name="toast_restore_started" msgid="7881679218971277385">"ਰੀਸਟੋਰ ਚਾਲੂ ਹੋ ਰਿਹਾ ਹੈ..."</string>
     <string name="toast_restore_ended" msgid="1764041639199696132">"ਰੀਸਟੋਰ ਖ਼ਤਮ ਹੋਇਆ"</string>
     <string name="toast_timeout" msgid="5276598587087626877">"ਓਪਰੇਸ਼ਨ ਦਾ ਸਮਾਂ ਸਮਾਪਤ"</string>
diff --git a/packages/CaptivePortalLogin/res/values-bn/strings.xml b/packages/CaptivePortalLogin/res/values-bn/strings.xml
index 886a667..b75d76e 100644
--- a/packages/CaptivePortalLogin/res/values-bn/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-bn/strings.xml
@@ -7,6 +7,6 @@
     <string name="action_bar_label" msgid="917235635415966620">"নেটওয়ার্কে সাইন-ইন করুন"</string>
     <string name="action_bar_title" msgid="5645564790486983117">"%1$s তে সাইন-ইন করুন"</string>
     <string name="ssl_error_warning" msgid="6653188881418638872">"আপনি যে নেটওয়ার্কে যোগ দেওয়ার চেষ্টা করছেন তাতে নিরাপত্তার সমস্যা আছে।"</string>
-    <string name="ssl_error_example" msgid="647898534624078900">"উদাহরণস্বরূপ, লগইন পৃষ্ঠাটি প্রদর্শিত প্রতিষ্ঠানের অন্তর্গত নাও হতে পারে৷"</string>
+    <string name="ssl_error_example" msgid="647898534624078900">"উদাহরণস্বরূপ, লগ-ইন পৃষ্ঠাটি প্রদর্শিত প্রতিষ্ঠানের অন্তর্গত নাও হতে পারে৷"</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"যাই হোক না কেন ব্রাউজারের মাধ্যমে অবিরত রাখুন"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-hi/strings.xml b/packages/CaptivePortalLogin/res/values-hi/strings.xml
index 1bc6879..1bacc46 100644
--- a/packages/CaptivePortalLogin/res/values-hi/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-hi/strings.xml
@@ -4,8 +4,8 @@
     <string name="app_name" msgid="5934709770924185752">"CaptivePortalLogin"</string>
     <string name="action_use_network" msgid="6076184727448466030">"इस नेटवर्क का उपयोग जैसा है वैसा ही करें"</string>
     <string name="action_do_not_use_network" msgid="4577366536956516683">"इस नेटवर्क का उपयोग न करें"</string>
-    <string name="action_bar_label" msgid="917235635415966620">"नेटवर्क में प्रवेश करें"</string>
-    <string name="action_bar_title" msgid="5645564790486983117">"%1$s में प्रवेश करें"</string>
+    <string name="action_bar_label" msgid="917235635415966620">"नेटवर्क में साइन इन करें"</string>
+    <string name="action_bar_title" msgid="5645564790486983117">"%1$s में साइन इन करें"</string>
     <string name="ssl_error_warning" msgid="6653188881418638872">"आप जिस नेटवर्क में शामिल होने का प्रयास कर रहे हैं उसमें सुरक्षा समस्‍याएं हैं."</string>
     <string name="ssl_error_example" msgid="647898534624078900">"उदाहरण के लिए, हो सकता है कि लॉगिन पृष्‍ठ दिखाए गए संगठन से संबद्ध ना हो."</string>
     <string name="ssl_error_continue" msgid="6492718244923937110">"ब्राउज़र के द्वारा फिर जारी रखें"</string>
diff --git a/packages/CarrierDefaultApp/res/values-bn/strings.xml b/packages/CarrierDefaultApp/res/values-bn/strings.xml
index e691839..448c42b 100644
--- a/packages/CarrierDefaultApp/res/values-bn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-bn/strings.xml
@@ -12,6 +12,6 @@
     <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"মোবাইল ডেটার স্ট্যাটাস"</string>
     <string name="action_bar_label" msgid="4290345990334377177">"মোবাইল নেটওয়ার্কে সাইন-ইন করুন"</string>
     <string name="ssl_error_warning" msgid="3127935140338254180">"আপনি যে নেটওয়ার্কে যোগ দেওয়ার চেষ্টা করছেন সেটিতে নিরাপত্তাজনিত সমস্যা আছে।"</string>
-    <string name="ssl_error_example" msgid="6188711843183058764">"যেমন, লগইন পৃষ্ঠাটি যে প্রতিষ্ঠানের পৃষ্ঠা বলে দেখানো আছে, আসলে তা নাও হতে পারে৷"</string>
+    <string name="ssl_error_example" msgid="6188711843183058764">"যেমন, লগ-ইন পৃষ্ঠাটি যে প্রতিষ্ঠানের পৃষ্ঠা বলে দেখানো আছে, আসলে তা নাও হতে পারে৷"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"যাই হোক, ব্রাউজারের মাধ্যমে চালিয়ে যান"</string>
 </resources>
diff --git a/packages/CarrierDefaultApp/res/values-hi/strings.xml b/packages/CarrierDefaultApp/res/values-hi/strings.xml
index 842bb5d..b9d6f42 100644
--- a/packages/CarrierDefaultApp/res/values-hi/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hi/strings.xml
@@ -6,11 +6,11 @@
     <string name="portal_notification_id" msgid="5155057562457079297">"मोबाइल डेटा खत्म हो गया है"</string>
     <string name="no_data_notification_id" msgid="668400731803969521">"आपका मोबाइल डेटा बंद कर दिया गया है"</string>
     <string name="portal_notification_detail" msgid="2295729385924660881">"%s वेबसाइट पर जाने के लिए टैप करें"</string>
-    <string name="no_data_notification_detail" msgid="3112125343857014825">"कृपया अपने सेवा प्रदाता %s से संपर्क करें"</string>
+    <string name="no_data_notification_detail" msgid="3112125343857014825">"कृपया अपने सेवा देने वाले %s से संपर्क करें"</string>
     <string name="no_mobile_data_connection_title" msgid="7449525772416200578">"कोई भी मोबाइल डेटा कनेक्शन नहीं है"</string>
     <string name="no_mobile_data_connection" msgid="544980465184147010">"%s के ज़रिए डेटा या रोमिंग योजना जोड़ें"</string>
     <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"मोबाइल डेटा की स्थिति"</string>
-    <string name="action_bar_label" msgid="4290345990334377177">"मोबाइल नेटवर्क में प्रवेश करें"</string>
+    <string name="action_bar_label" msgid="4290345990334377177">"मोबाइल नेटवर्क में साइन इन करें"</string>
     <string name="ssl_error_warning" msgid="3127935140338254180">"आप जिस नेटवर्क में शामिल होने की कोशिश कर रहे हैं उसमें सुरक्षा से जुड़ी समस्‍याएं हैं."</string>
     <string name="ssl_error_example" msgid="6188711843183058764">"उदाहरण के लिए, हो सकता है कि लॉगिन पेज दिखाए गए संगठन का ना हो."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"ब्राउज़र के ज़रिए किसी भी तरह जारी रखें"</string>
diff --git a/packages/CarrierDefaultApp/res/values-pa/strings.xml b/packages/CarrierDefaultApp/res/values-pa/strings.xml
index c0da8fb..f4d4053 100644
--- a/packages/CarrierDefaultApp/res/values-pa/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pa/strings.xml
@@ -8,7 +8,7 @@
     <string name="portal_notification_detail" msgid="2295729385924660881">"%s ਵੈੱਬਸਾਈਟ \'ਤੇ ਜਾਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="no_data_notification_detail" msgid="3112125343857014825">"ਕਿਰਪਾ ਕਰਕੇ ਆਪਣੇ ਸੇਵਾ ਪ੍ਰਦਾਨਕ %s ਨੂੰ ਸੰਪਰਕ ਕਰੋ"</string>
     <string name="no_mobile_data_connection_title" msgid="7449525772416200578">"ਕੋਈ ਮੋਬਾਈਲ ਡਾਟਾ ਕਨੈਕਸ਼ਨ ਨਹੀਂ"</string>
-    <string name="no_mobile_data_connection" msgid="544980465184147010">"%s ਰਾਹੀਂ ਡੈਟਾ ਜਾਂ ਰੋਮਿੰਗ ਯੋਜਨਾ ਸ਼ਾਮਲ ਕਰੋ"</string>
+    <string name="no_mobile_data_connection" msgid="544980465184147010">"%s ਰਾਹੀਂ ਡਾਟਾ ਜਾਂ ਰੋਮਿੰਗ ਯੋਜਨਾ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"ਮੋਬਾਈਲ ਡਾਟੇ ਦੀ ਸਥਿਤੀ"</string>
     <string name="action_bar_label" msgid="4290345990334377177">"ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਵਿੱਚ ਸਾਈਨ-ਇਨ ਕਰੋ"</string>
     <string name="ssl_error_warning" msgid="3127935140338254180">"ਤੁਸੀਂ ਜਿਸ ਨੈੱਟਵਰਕ ਵਿੱਚ ਸ਼ਾਮਲ ਹੋਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰ ਰਹੇ ਹੋ ਉਸ ਵਿੱਚ ਸੁਰੱਖਿਆ ਸਬੰਧੀ ਸਮੱਸਿਆਵਾਂ ਹਨ।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-ta/strings.xml b/packages/CarrierDefaultApp/res/values-ta/strings.xml
index 111f8d1..1a786fa 100644
--- a/packages/CarrierDefaultApp/res/values-ta/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ta/strings.xml
@@ -3,13 +3,13 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
     <string name="android_system_label" msgid="2797790869522345065">"தொலைத்தொடர்பு நிறுவனம்"</string>
-    <string name="portal_notification_id" msgid="5155057562457079297">"மொபைல் தரவு தீர்ந்துவிட்டது"</string>
-    <string name="no_data_notification_id" msgid="668400731803969521">"மொபைல் தரவு முடக்கப்பட்டது"</string>
+    <string name="portal_notification_id" msgid="5155057562457079297">"மொபைல் டேட்டா தீர்ந்துவிட்டது"</string>
+    <string name="no_data_notification_id" msgid="668400731803969521">"மொபைல் டேட்டா முடக்கப்பட்டது"</string>
     <string name="portal_notification_detail" msgid="2295729385924660881">"%s இணையதளத்திற்குச் செல்ல, தட்டவும்"</string>
     <string name="no_data_notification_detail" msgid="3112125343857014825">"%s எனும் உங்கள் சேவை வழங்குநரைத் தொடர்புகொள்ளவும்"</string>
-    <string name="no_mobile_data_connection_title" msgid="7449525772416200578">"மொபைல் தரவு இணைப்பு இல்லை"</string>
+    <string name="no_mobile_data_connection_title" msgid="7449525772416200578">"மொபைல் டேட்டா இணைப்பு இல்லை"</string>
     <string name="no_mobile_data_connection" msgid="544980465184147010">"%s மூலம் தரவு அல்லது ரோமிங் திட்டத்தைச் சேர்க்கவும்"</string>
-    <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"மொபைல் தரவின் நிலை"</string>
+    <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"மொபைல் டேட்டாவின் நிலை"</string>
     <string name="action_bar_label" msgid="4290345990334377177">"மொபைல் நெட்வொர்க்கில் உள்நுழையவும்"</string>
     <string name="ssl_error_warning" msgid="3127935140338254180">"நீங்கள் சேர முயலும் நெட்வொர்க்கில் பாதுகாப்புச் சிக்கல்கள் உள்ளன."</string>
     <string name="ssl_error_example" msgid="6188711843183058764">"எடுத்துக்காட்டாக, உள்நுழைவுப் பக்கமானது காட்டப்படும் அமைப்பிற்குச் சொந்தமானதாக இல்லாமல் இருக்கலாம்."</string>
diff --git a/packages/EasterEgg/AndroidManifest.xml b/packages/EasterEgg/AndroidManifest.xml
index 14861c26..172490d 100644
--- a/packages/EasterEgg/AndroidManifest.xml
+++ b/packages/EasterEgg/AndroidManifest.xml
@@ -84,5 +84,16 @@
                 <action android:name="android.service.quicksettings.action.QS_TILE" />
             </intent-filter>
         </service>
+
+        <!-- FileProvider for sending pictures -->
+        <provider
+                android:name="android.support.v4.content.FileProvider"
+                android:authorities="com.android.egg.fileprovider"
+                android:grantUriPermissions="true"
+                android:exported="false">
+            <meta-data
+                    android:name="android.support.FILE_PROVIDER_PATHS"
+                    android:resource="@xml/filepaths" />
+        </provider>
     </application>
 </manifest>
diff --git a/packages/EasterEgg/res/drawable/food_cookie.xml b/packages/EasterEgg/res/drawable/food_cookie.xml
new file mode 100644
index 0000000..74dd134
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/food_cookie.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2017 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <group>
+        <path
+            android:fillColor="#55FFFFFF"
+            android:fillType="evenOdd"
+            android:pathData="M5.71 18.29A8.99 8.99 0 0 0 22 13c0-3-1.46-5.65-3.71-7.29A8.99 8.99 0 0 0 2 11c0 3 1.46 5.65 3.71 7.29z"/>
+        <path
+            android:fillColor="#FFFFFFFF"
+            android:fillType="evenOdd"
+            android:pathData="M7.25 19.18A8.5 8.5 0 0 0 19.19 7.24 9 9 0 0 1 7.24 19.19z"/>
+        <path
+            android:fillColor="#55FFFFFF"
+            android:pathData="M10.5 3a0.5 0.5 0 1 1 1 0v2.05a0.5 0.5 0 1 1-1 0V3zm3.1 0.42a0.5 0.5 0 0 1 0.93 0.39l-0.8 1.88A0.5 0.5 0 1 1 12.8 5.3l0.8-1.88zm2.7 1.57a0.5 0.5 0 1 1 0.71 0.7l-1.45 1.46a0.5 0.5 0 0 1-0.7-0.71l1.44-1.45zm1.9 2.5a0.5 0.5 0 0 1 0.38 0.92l-1.9 0.77a0.5 0.5 0 0 1-0.37-0.93l1.9-0.77zM19 10.5a0.5 0.5 0 1 1 0 1h-2.05a0.5 0.5 0 0 1 0-1H19zm-0.42 3.1a0.5 0.5 0 0 1-0.39 0.93l-1.88-0.8a0.5 0.5 0 1 1 0.39-0.92l1.88 0.8zm-1.57 2.7a0.5 0.5 0 1 1-0.7 0.71l-1.46-1.45a0.5 0.5 0 0 1 0.71-0.7l1.45 1.44zm-2.5 1.9a0.5 0.5 0 1 1-0.92 0.38l-0.77-1.9a0.5 0.5 0 0 1 0.93-0.37l0.77 1.9zM11.5 19a0.5 0.5 0 1 1-1 0v-2.05a0.5 0.5 0 0 1 1 0V19zm-3.1-0.42a0.5 0.5 0 0 1-0.93-0.39l0.8-1.88A0.5 0.5 0 0 1 9.2 16.7l-0.8 1.88zm-2.7-1.57a0.5 0.5 0 1 1-0.71-0.7l1.45-1.46a0.5 0.5 0 0 1 0.7 0.71L5.7 17.01zm-1.9-2.48a0.5 0.5 0 0 1-0.38-0.92l1.88-0.8a0.5 0.5 0 0 1 0.4 0.92l-1.9 0.8zM3 11.5a0.5 0.5 0 1 1 0-1h2.05a0.5 0.5 0 1 1 0 1H3zm0.42-3.1A0.5 0.5 0 0 1 3.8 7.46l1.88 0.8A0.5 0.5 0 1 1 5.3 9.2L3.42 8.4zm1.57-2.7a0.5 0.5 0 1 1 0.7-0.71l1.46 1.45a0.5 0.5 0 0 1-0.71 0.7L4.99 5.7zm2.5-1.9A0.5 0.5 0 0 1 8.4 3.41l0.77 1.9a0.5 0.5 0 0 1-0.93 0.37L7.48 3.8z"/>
+    </group>
+</vector>
\ No newline at end of file
diff --git a/packages/EasterEgg/res/values/strings.xml b/packages/EasterEgg/res/values/strings.xml
index 8478a43..61e3834 100644
--- a/packages/EasterEgg/res/values/strings.xml
+++ b/packages/EasterEgg/res/values/strings.xml
@@ -17,6 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
     <string name="app_name" translatable="false">Android Easter Egg</string>
     <string name="notification_name" translatable="false">Android Neko</string>
+    <string name="notification_channel_name" translatable="false">New cats</string>
     <string name="default_tile_name" translatable="false">\????</string>
     <string name="notification_title" translatable="false">A cat is here.</string>
     <string name="default_cat_name" translatable="false">Cat #%s</string>
@@ -34,7 +35,7 @@
         <item>@drawable/food_bits</item>
         <item>@drawable/food_sysuituna</item>
         <item>@drawable/food_chicken</item>
-        <item>@drawable/food_donut</item>
+        <item>@drawable/food_cookie</item>
     </array>
     <integer-array name="food_intervals">
         <item>0</item>
diff --git a/packages/EasterEgg/res/xml/filepaths.xml b/packages/EasterEgg/res/xml/filepaths.xml
new file mode 100644
index 0000000..2130025
--- /dev/null
+++ b/packages/EasterEgg/res/xml/filepaths.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2017 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.
+-->
+<paths>
+    <external-path name="cats" path="Pictures/Cats" />
+</paths>
\ No newline at end of file
diff --git a/packages/EasterEgg/src/com/android/egg/neko/Cat.java b/packages/EasterEgg/src/com/android/egg/neko/Cat.java
index a4df372..dd1bd07 100644
--- a/packages/EasterEgg/src/com/android/egg/neko/Cat.java
+++ b/packages/EasterEgg/src/com/android/egg/neko/Cat.java
@@ -31,6 +31,8 @@
 import com.android.egg.R;
 import com.android.internal.logging.MetricsLogger;
 
+import static com.android.egg.neko.NekoLand.CHAN_ID;
+
 public class Cat extends Drawable {
     public static final long[] PURR = {0, 40, 20, 40, 20, 40, 20, 40, 20, 40, 20, 40};
 
@@ -218,6 +220,7 @@
                 .setContentText(getName())
                 .setContentIntent(PendingIntent.getActivity(context, 0, intent, 0))
                 .setAutoCancel(true)
+                .setChannel(CHAN_ID)
                 .setVibrate(PURR)
                 .addExtras(extras);
     }
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java b/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java
index 689e381..d2e37d8 100644
--- a/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java
+++ b/packages/EasterEgg/src/com/android/egg/neko/NekoLand.java
@@ -31,6 +31,7 @@
 import android.os.Bundle;
 import android.os.Environment;
 import android.provider.MediaStore.Images;
+import android.support.v4.content.FileProvider;
 import android.support.v7.widget.GridLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.util.Log;
@@ -56,6 +57,8 @@
 import java.util.List;
 
 public class NekoLand extends Activity implements PrefsListener {
+    public static String CHAN_ID = "EGG";
+
     public static boolean DEBUG = false;
     public static boolean DEBUG_NOTIFICATIONS = false;
 
@@ -289,10 +292,13 @@
                         new String[] {png.toString()},
                         new String[] {"image/png"},
                         null);
-                Uri uri = Uri.fromFile(png);
+                Log.v("Neko", "cat file: " + png);
+                Uri uri = FileProvider.getUriForFile(this, "com.android.egg.fileprovider", png);
+                Log.v("Neko", "cat uri: " + uri);
                 Intent intent = new Intent(Intent.ACTION_SEND);
                 intent.putExtra(Intent.EXTRA_STREAM, uri);
                 intent.putExtra(Intent.EXTRA_SUBJECT, cat.getName());
+                intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                 intent.setType("image/png");
                 startActivity(Intent.createChooser(intent, null));
                 cat.logShare(this);
diff --git a/packages/EasterEgg/src/com/android/egg/neko/NekoService.java b/packages/EasterEgg/src/com/android/egg/neko/NekoService.java
index 808ec36..42506e6 100644
--- a/packages/EasterEgg/src/com/android/egg/neko/NekoService.java
+++ b/packages/EasterEgg/src/com/android/egg/neko/NekoService.java
@@ -15,15 +15,15 @@
 package com.android.egg.neko;
 
 import android.app.Notification;
+import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.job.JobInfo;
 import android.app.job.JobParameters;
 import android.app.job.JobScheduler;
 import android.app.job.JobService;
-import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
+import android.net.Uri;
 import android.os.Bundle;
 
 import java.util.List;
@@ -33,6 +33,9 @@
 
 import java.util.Random;
 
+import static com.android.egg.neko.Cat.PURR;
+import static com.android.egg.neko.NekoLand.CHAN_ID;
+
 public class NekoService extends JobService {
 
     private static final String TAG = "NekoService";
@@ -40,6 +43,7 @@
     public static int JOB_ID = 42;
 
     public static int CAT_NOTIFICATION = 1;
+    public static int DEBUG_NOTIFICATION = 1234;
 
     public static float CAT_CAPTURE_PROB = 1.0f; // generous
 
@@ -50,6 +54,18 @@
 
     public static float INTERVAL_JITTER_FRAC = 0.25f;
 
+    private static void setupNotificationChannels(Context context) {
+        NotificationManager noman = context.getSystemService(NotificationManager.class);
+        NotificationChannel eggChan = new NotificationChannel(CHAN_ID,
+                context.getString(R.string.notification_channel_name),
+                NotificationManager.IMPORTANCE_DEFAULT);
+        eggChan.setSound(Uri.EMPTY, Notification.AUDIO_ATTRIBUTES_DEFAULT); // cats are quiet
+        eggChan.setVibrationPattern(PURR); // not totally quiet though
+        eggChan.setBlockableSystem(true); // unlike a real cat, you can push this one off your lap
+        eggChan.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); // cats sit in the window
+        noman.createNotificationChannel(eggChan);
+    }
+
     @Override
     public boolean onStartJob(JobParameters params) {
         Log.v(TAG, "Starting job: " + String.valueOf(params));
@@ -64,8 +80,9 @@
             final Notification.Builder builder
                     = cat.buildNotification(this)
                         .setContentTitle("DEBUG")
+                        .setChannel(NekoLand.CHAN_ID)
                         .setContentText("Ran job: " + params);
-            noman.notify(1, builder.build());
+            noman.notify(DEBUG_NOTIFICATION, builder.build());
         }
 
         final PrefState prefs = new PrefState(this);
@@ -111,6 +128,8 @@
     }
 
     public static void registerJob(Context context, long intervalMinutes) {
+        setupNotificationChannels(context);
+
         JobScheduler jss = context.getSystemService(JobScheduler.class);
         jss.cancel(JOB_ID);
         long interval = intervalMinutes * MINUTES;
@@ -126,12 +145,13 @@
 
         if (NekoLand.DEBUG_NOTIFICATIONS) {
             NotificationManager noman = context.getSystemService(NotificationManager.class);
-            noman.notify(500, new Notification.Builder(context)
+            noman.notify(DEBUG_NOTIFICATION, new Notification.Builder(context)
                     .setSmallIcon(R.drawable.stat_icon)
                     .setContentTitle(String.format("Job scheduled in %d min", (interval / MINUTES)))
                     .setContentText(String.valueOf(jobInfo))
                     .setPriority(Notification.PRIORITY_MIN)
                     .setCategory(Notification.CATEGORY_SERVICE)
+                    .setChannel(NekoLand.CHAN_ID)
                     .setShowWhen(true)
                     .build());
         }
diff --git a/packages/ExternalStorageProvider/res/values-bn/strings.xml b/packages/ExternalStorageProvider/res/values-bn/strings.xml
index f1cb2f2..264d82a 100644
--- a/packages/ExternalStorageProvider/res/values-bn/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-bn/strings.xml
@@ -16,8 +16,8 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="7123375275748530234">"বাহ্যিক সঞ্চয়স্থান"</string>
-    <string name="storage_description" msgid="8541974407321172792">"স্থানীয় সঞ্চয়স্থান"</string>
-    <string name="root_internal_storage" msgid="827844243068584127">"অভ্যন্তরীণ সঞ্চয়স্থান"</string>
+    <string name="app_label" msgid="7123375275748530234">"এক্সটারনাল স্টোরেজ"</string>
+    <string name="storage_description" msgid="8541974407321172792">"স্থানীয় স্টোরেজ"</string>
+    <string name="root_internal_storage" msgid="827844243068584127">"ইন্টারনাল স্টোরেজ"</string>
     <string name="root_documents" msgid="4051252304075469250">"দস্তাবেজগুলি"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-mr/strings.xml b/packages/InputDevices/res/values-mr/strings.xml
index 70b7c77..e8575a8 100644
--- a/packages/InputDevices/res/values-mr/strings.xml
+++ b/packages/InputDevices/res/values-mr/strings.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="8016145283189546017">"इनपुट डीव्हाइस"</string>
+    <string name="app_label" msgid="8016145283189546017">"इनपुट डिव्हाइस"</string>
     <string name="keyboard_layouts_label" msgid="6688773268302087545">"Android कीबोर्ड"</string>
     <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"इंग्रजी (यूके)"</string>
     <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"इंग्रजी (यूएस)"</string>
diff --git a/packages/MtpDocumentsProvider/res/values-gu/strings.xml b/packages/MtpDocumentsProvider/res/values-gu/strings.xml
index 40ec38d..468bd9d 100644
--- a/packages/MtpDocumentsProvider/res/values-gu/strings.xml
+++ b/packages/MtpDocumentsProvider/res/values-gu/strings.xml
@@ -20,6 +20,6 @@
     <string name="downloads_app_label" msgid="7120690641874849726">"ડાઉનલોડ્સ"</string>
     <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
     <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> ની ફાઇલોને ઍક્સેસ કરી રહ્યાં છે"</string>
-    <string name="error_busy_device" msgid="3997316850357386589">"અન્ય ઉપકરણ વ્યસ્ત છે. તે ઉપલબ્ધ ન થાય ત્યાં સુધી તમે ફાઇલોને સ્થાનાંતરિત કરી શકતાં નથી."</string>
+    <string name="error_busy_device" msgid="3997316850357386589">"અન્ય ઉપકરણ વ્યસ્ત છે. તે ઉપલબ્ધ ન થાય ત્યાં સુધી તમે ફાઇલોને ટ્રાન્સફર કરી શકતાં નથી."</string>
     <string name="error_locked_device" msgid="7557872102188356147">"કોઈ ફાઇલો મળી નહીં. અન્ય ઉપકરણ લૉક કરેલ હોઈ શકે છે. જો આમ હોય, તો તેને અનલૉક કરો અને ફરી પ્રયાસ કરો."</string>
 </resources>
diff --git a/packages/MtpDocumentsProvider/res/values-mr/strings.xml b/packages/MtpDocumentsProvider/res/values-mr/strings.xml
index 9b50e93..89a9d14 100644
--- a/packages/MtpDocumentsProvider/res/values-mr/strings.xml
+++ b/packages/MtpDocumentsProvider/res/values-mr/strings.xml
@@ -20,6 +20,6 @@
     <string name="downloads_app_label" msgid="7120690641874849726">"डाउनलोड"</string>
     <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
     <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> मधून फायलींंमध्ये प्रवेश करीत आहे"</string>
-    <string name="error_busy_device" msgid="3997316850357386589">"दुसरे डीव्हाइस व्यस्त आहे. ते उपलब्‍ध होईपर्यंत तुम्ही फायली ट्रांसफर करू शकत नाही."</string>
-    <string name="error_locked_device" msgid="7557872102188356147">"कोणत्याही फायली आढळल्या नाहीत. दुसरे डीव्हाइस कदाचित बंद असू शकते. तसे असल्यास, ते अनलॉक करा आणि पुन्हा प्रयत्न करा."</string>
+    <string name="error_busy_device" msgid="3997316850357386589">"दुसरे डिव्हाइस व्यस्त आहे. ते उपलब्‍ध होईपर्यंत तुम्ही फायली ट्रांसफर करू शकत नाही."</string>
+    <string name="error_locked_device" msgid="7557872102188356147">"कोणत्याही फायली आढळल्या नाहीत. दुसरे डिव्हाइस कदाचित बंद असू शकते. तसे असल्यास, ते अनलॉक करा आणि पुन्हा प्रयत्न करा."</string>
 </resources>
diff --git a/packages/MtpDocumentsProvider/res/values-pa/strings.xml b/packages/MtpDocumentsProvider/res/values-pa/strings.xml
index 236db6f..7e3b892 100644
--- a/packages/MtpDocumentsProvider/res/values-pa/strings.xml
+++ b/packages/MtpDocumentsProvider/res/values-pa/strings.xml
@@ -21,5 +21,5 @@
     <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
     <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> ਦੀਆਂ ਫ਼ਾਈਲਾਂ \'ਤੇ ਪਹੁੰਚ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string>
     <string name="error_busy_device" msgid="3997316850357386589">"ਦੂਜਾ ਡੀਵਾਈਸ ਰੁਝੇਵੇਂ ਵਿੱਚ ਹੈ। ਉਸਦੇ ਉਪਲਬਧ ਹੋਣ ਤੱਕ ਤੁਸੀਂ ਫ਼ਾਈਲਾਂ ਦਾ ਤਬਾਦਲਾ ਨਹੀਂ ਕਰ ਸਕਦੇ।"</string>
-    <string name="error_locked_device" msgid="7557872102188356147">"ਕੋਈ ਫ਼ਾਈਲਾਂ ਨਹੀਂ ਮਿਲੀਆਂ। ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਦੂਜਾ ਡੀਵਾਈਸ ਲੌਕ ਹੋਵੇ। ਜੇਕਰ ਇੰਝ ਹੈ, ਤਾਂ ਉਸਨੂੰ ਅਨਲੌਕ ਕਰੋ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="error_locked_device" msgid="7557872102188356147">"ਕੋਈ ਫ਼ਾਈਲਾਂ ਨਹੀਂ ਮਿਲੀਆਂ। ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਦੂਜਾ ਡੀਵਾਈਸ ਲਾਕ ਹੋਵੇ। ਜੇਕਰ ਇੰਝ ਹੈ, ਤਾਂ ਉਸਨੂੰ ਅਣਲਾਕ ਕਰੋ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
 </resources>
diff --git a/packages/PrintSpooler/res/values-bn/strings.xml b/packages/PrintSpooler/res/values-bn/strings.xml
index 1791358..d2751f1 100644
--- a/packages/PrintSpooler/res/values-bn/strings.xml
+++ b/packages/PrintSpooler/res/values-bn/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4469836075319831821">"প্রিন্ট স্পোলার"</string>
-    <string name="more_options_button" msgid="2243228396432556771">"আরো বিকল্প"</string>
+    <string name="more_options_button" msgid="2243228396432556771">"আরও বিকল্প"</string>
     <string name="label_destination" msgid="9132510997381599275">"গন্তব্য"</string>
     <string name="label_copies" msgid="3634531042822968308">"প্রতিলিপিগুলি"</string>
     <string name="label_copies_summary" msgid="3861966063536529540">"অনুলিপিগুলি:"</string>
@@ -27,7 +27,7 @@
     <string name="label_duplex" msgid="5370037254347072243">"দ্বিভুজ"</string>
     <string name="label_orientation" msgid="2853142581990496477">"সজ্জা"</string>
     <string name="label_pages" msgid="7768589729282182230">"পৃষ্ঠাগুলি"</string>
-    <string name="destination_default_text" msgid="5422708056807065710">"একটি মুদ্রক নির্বাচন করুন"</string>
+    <string name="destination_default_text" msgid="5422708056807065710">"একটি মুদ্রক বেছে নিন"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"সমস্ত <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> এর পরিসর"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"যেমন, ১—৫,৮,১১—১৩"</string>
@@ -35,7 +35,7 @@
     <string name="install_for_print_preview" msgid="6366303997385509332">"প্রিভিউ দেখার জন্য PDF ভিউয়ার ইনস্টল করুন"</string>
     <string name="printing_app_crashed" msgid="854477616686566398">"প্রিন্ট অ্যাপ্লিকেশান ক্র্যাশ করছে"</string>
     <string name="generating_print_job" msgid="3119608742651698916">"প্রিন্ট কার্য তৈরি করা হচ্ছে"</string>
-    <string name="save_as_pdf" msgid="5718454119847596853">"PDF হিসেবে সংরক্ষণ করুন"</string>
+    <string name="save_as_pdf" msgid="5718454119847596853">"পিডিএফ হিসাবে সেভ করুন"</string>
     <string name="all_printers" msgid="5018829726861876202">"সমস্ত মুদ্রক…"</string>
     <string name="print_dialog" msgid="32628687461331979">"প্রিন্ট ডায়লগ"</string>
     <string name="current_page_template" msgid="5145005201131935302">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
@@ -44,33 +44,33 @@
     <string name="expand_handle" msgid="7282974448109280522">"প্রসারিত করার হ্যান্ডেল"</string>
     <string name="collapse_handle" msgid="6886637989442507451">"সঙ্কুচিত করার হ্যান্ডেল"</string>
     <string name="print_button" msgid="645164566271246268">"প্রিন্ট করুন"</string>
-    <string name="savetopdf_button" msgid="2976186791686924743">"PDF হিসেবে সংরক্ষণ করুন"</string>
+    <string name="savetopdf_button" msgid="2976186791686924743">"পিডিএফ হিসাবে সেভ করুন"</string>
     <string name="print_options_expanded" msgid="6944679157471691859">"প্রিন্ট বিকল্প প্রসারিত হয়েছে"</string>
     <string name="print_options_collapsed" msgid="7455930445670414332">"প্রিন্ট বিকল্প সংকুচিত হয়েছে"</string>
-    <string name="search" msgid="5421724265322228497">"অনুসন্ধান করুন"</string>
+    <string name="search" msgid="5421724265322228497">"খুঁজুন"</string>
     <string name="all_printers_label" msgid="3178848870161526399">"সমস্ত মুদ্রক"</string>
     <string name="add_print_service_label" msgid="5356702546188981940">"পরিষেবা যোগ করুন"</string>
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"অনুসন্ধান বাক্স দেখানো হচ্ছে"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"অনুসন্ধান বাক্স লুকানো রয়েছে"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"মুদ্রক যোগ করুন"</string>
-    <string name="print_select_printer" msgid="7388760939873368698">"মুদ্রক নির্বাচন করুন"</string>
+    <string name="print_select_printer" msgid="7388760939873368698">"মুদ্রক বেছে নিন"</string>
     <string name="print_forget_printer" msgid="5035287497291910766">"মুদ্রকটিকে সরিয়ে দিন"</string>
     <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
       <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g>টি মুদ্রক খুঁজে পাওয়া গেছে</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g>টি মুদ্রক খুঁজে পাওয়া গেছে</item>
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
-    <string name="printer_info_desc" msgid="7181988788991581654">"এই মুদ্রকটির বিষয়ে আরো তথ্য"</string>
+    <string name="printer_info_desc" msgid="7181988788991581654">"এই মুদ্রকটির বিষয়ে আরও তথ্য"</string>
     <string name="notification_channel_progress" msgid="872788690775721436">"এগুলি প্রিন্ট হচ্ছে"</string>
     <string name="notification_channel_failure" msgid="9042250774797916414">"এগুলি প্রিন্ট করা যায়নি"</string>
     <string name="could_not_create_file" msgid="3425025039427448443">"ফাইল তৈরি করা গেল না"</string>
-    <string name="print_services_disabled_toast" msgid="9089060734685174685">"কিছু মুদ্রণ পরিষেবা অক্ষম করা আছে"</string>
+    <string name="print_services_disabled_toast" msgid="9089060734685174685">"কিছু প্রিন্ট পরিষেবা অক্ষম করা আছে"</string>
     <string name="print_searching_for_printers" msgid="6550424555079932867">"মুদ্রকগুলি অনুসন্ধান করা হচ্ছে"</string>
     <string name="print_no_print_services" msgid="8561247706423327966">"প্রিন্ট পরিষেবা সক্ষম নেই"</string>
     <string name="print_no_printers" msgid="4869403323900054866">"কোনো মুদ্রক পাওয়া যায়নি"</string>
     <string name="cannot_add_printer" msgid="7840348733668023106">"মুদ্রকগুলি যোগ করা যাবে না"</string>
-    <string name="select_to_add_printers" msgid="3800709038689830974">"মুদ্রক যোগ করতে নির্বাচন করুন"</string>
-    <string name="enable_print_service" msgid="3482815747043533842">"সক্ষম করতে নির্বাচন করুন"</string>
+    <string name="select_to_add_printers" msgid="3800709038689830974">"মুদ্রক যোগ করতে বেছে নিন"</string>
+    <string name="enable_print_service" msgid="3482815747043533842">"সক্ষম করতে বেছে নিন"</string>
     <string name="enabled_services_title" msgid="7036986099096582296">"সক্ষম করা পরিষেবাগুলি"</string>
     <string name="recommended_services_title" msgid="3799434882937956924">"প্রস্তাবিত পরিষেবাগুলি"</string>
     <string name="disabled_services_title" msgid="7313253167968363211">"অক্ষম করা পরিষেবাগুলি"</string>
@@ -84,7 +84,7 @@
     <string name="failed_notification_title_template" msgid="2256217208186530973">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> মুদ্রক ত্রুটি"</string>
     <string name="blocked_notification_title_template" msgid="1175435827331588646">"মুদ্রক <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> অবরুদ্ধ করেছে"</string>
     <string name="cancel" msgid="4373674107267141885">"বাতিল করুন"</string>
-    <string name="restart" msgid="2472034227037808749">"পুনর্সূচনা"</string>
+    <string name="restart" msgid="2472034227037808749">"রিস্টার্ট করুন"</string>
     <string name="no_connection_to_printer" msgid="2159246915977282728">"মুদ্রকে কোনো সংযোগ নেই"</string>
     <string name="reason_unknown" msgid="5507940196503246139">"অজানা"</string>
     <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> ব্যবহার করবেন?"</string>
@@ -100,7 +100,7 @@
   </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"পোর্ট্রেট"</item>
-    <item msgid="3199660090246166812">"ভূদৃশ্য"</item>
+    <item msgid="3199660090246166812">"ল্যান্ডস্কেপ"</item>
   </string-array>
     <string name="print_write_error_message" msgid="5787642615179572543">"ফাইলে লেখা যায়নি"</string>
     <string name="print_error_default_message" msgid="8602678405502922346">"দুঃখিত, এটি কাজ করেনি৷ আবার চেষ্টা করুন৷"</string>
diff --git a/packages/PrintSpooler/res/values-gu/strings.xml b/packages/PrintSpooler/res/values-gu/strings.xml
index 7ad8d57..4d035da 100644
--- a/packages/PrintSpooler/res/values-gu/strings.xml
+++ b/packages/PrintSpooler/res/values-gu/strings.xml
@@ -84,7 +84,7 @@
     <string name="failed_notification_title_template" msgid="2256217208186530973">"પ્રિન્ટર ભૂલ <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="blocked_notification_title_template" msgid="1175435827331588646">"પ્રિન્ટરે <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> અવરોધિત કર્યું"</string>
     <string name="cancel" msgid="4373674107267141885">"રદ કરો"</string>
-    <string name="restart" msgid="2472034227037808749">"પુનઃપ્રારંભ કરો"</string>
+    <string name="restart" msgid="2472034227037808749">"રિસ્ટાર્ટ કરો"</string>
     <string name="no_connection_to_printer" msgid="2159246915977282728">"પ્રિન્ટર માટે કોઈ કનેક્શન નથી"</string>
     <string name="reason_unknown" msgid="5507940196503246139">"અજાણ્યું"</string>
     <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> નો ઉપયોગ કરીએ?"</string>
diff --git a/packages/PrintSpooler/res/values-hi/strings.xml b/packages/PrintSpooler/res/values-hi/strings.xml
index 5f3fb5d..37777d2 100644
--- a/packages/PrintSpooler/res/values-hi/strings.xml
+++ b/packages/PrintSpooler/res/values-hi/strings.xml
@@ -41,8 +41,8 @@
     <string name="current_page_template" msgid="5145005201131935302">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
     <string name="page_description_template" msgid="6831239682256197161">"<xliff:g id="PAGE_COUNT">%2$d</xliff:g> में से पेज <xliff:g id="CURRENT_PAGE">%1$d</xliff:g>"</string>
     <string name="summary_template" msgid="8899734908625669193">"सारांश, प्रतियां <xliff:g id="COPIES">%1$s</xliff:g>, काग़ज़ का आकार <xliff:g id="PAPER_SIZE">%2$s</xliff:g>"</string>
-    <string name="expand_handle" msgid="7282974448109280522">"हैंडल विस्तृत करें"</string>
-    <string name="collapse_handle" msgid="6886637989442507451">"हैंडल संक्षिप्त करें"</string>
+    <string name="expand_handle" msgid="7282974448109280522">"हैंडल का विस्तार करें"</string>
+    <string name="collapse_handle" msgid="6886637989442507451">"हैंडल को छोटा करें"</string>
     <string name="print_button" msgid="645164566271246268">"प्रिंट करें"</string>
     <string name="savetopdf_button" msgid="2976186791686924743">"पीडीएफ़ में सेव करें"</string>
     <string name="print_options_expanded" msgid="6944679157471691859">"प्रिंट विकल्पों को विस्तृत किया गया"</string>
diff --git a/packages/PrintSpooler/res/values-iw/strings.xml b/packages/PrintSpooler/res/values-iw/strings.xml
index 6540ca1..22ef612 100644
--- a/packages/PrintSpooler/res/values-iw/strings.xml
+++ b/packages/PrintSpooler/res/values-iw/strings.xml
@@ -88,7 +88,7 @@
     <string name="failed_notification_title_template" msgid="2256217208186530973">"שגיאת מדפסת ב-<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="blocked_notification_title_template" msgid="1175435827331588646">"המדפסת חסמה את <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancel" msgid="4373674107267141885">"ביטול"</string>
-    <string name="restart" msgid="2472034227037808749">"הפעל מחדש"</string>
+    <string name="restart" msgid="2472034227037808749">"הפעלה מחדש"</string>
     <string name="no_connection_to_printer" msgid="2159246915977282728">"אין חיבור למדפסת"</string>
     <string name="reason_unknown" msgid="5507940196503246139">"לא ידוע"</string>
     <string name="print_service_security_warning_title" msgid="2160752291246775320">"האם להשתמש ב-<xliff:g id="SERVICE">%1$s</xliff:g>?"</string>
diff --git a/packages/PrintSpooler/res/values-my/strings.xml b/packages/PrintSpooler/res/values-my/strings.xml
index c581e59..7c7b03e6 100644
--- a/packages/PrintSpooler/res/values-my/strings.xml
+++ b/packages/PrintSpooler/res/values-my/strings.xml
@@ -49,7 +49,7 @@
     <string name="print_options_collapsed" msgid="7455930445670414332">"ပရင့်ထုတ် ရွေးစရာများကို ခေါက်ထား"</string>
     <string name="search" msgid="5421724265322228497">"ရှာဖွေခြင်း"</string>
     <string name="all_printers_label" msgid="3178848870161526399">"စာထုတ်စက် အားလုံး"</string>
-    <string name="add_print_service_label" msgid="5356702546188981940">"ဆားဗစ် အသစ်ထည့်ရန်"</string>
+    <string name="add_print_service_label" msgid="5356702546188981940">"ဝန်ဆောင်မှုထည့်ရန်"</string>
     <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"ရှာဖွေစရာ နေရာ မြင်တွေ့ရပါသည်"</string>
     <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"ရှာဖွေရန် နေရာ ပျောက်ကွယ်နေပါသည်"</string>
     <string name="print_add_printer" msgid="1088656468360653455">"စာထုတ်စက်ကို ထည့်ပါ"</string>
diff --git a/packages/PrintSpooler/res/values-ne/strings.xml b/packages/PrintSpooler/res/values-ne/strings.xml
index c5f5978..18f96dd 100644
--- a/packages/PrintSpooler/res/values-ne/strings.xml
+++ b/packages/PrintSpooler/res/values-ne/strings.xml
@@ -84,7 +84,7 @@
     <string name="failed_notification_title_template" msgid="2256217208186530973">"प्रिन्टर त्रुटि <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="blocked_notification_title_template" msgid="1175435827331588646">"प्रिन्टर ब्लक गरियो <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
     <string name="cancel" msgid="4373674107267141885">"रद्द गर्नुहोस्"</string>
-    <string name="restart" msgid="2472034227037808749">"पुनःस्टार्ट गर्नुहोस्"</string>
+    <string name="restart" msgid="2472034227037808749">"पुनः सुरु गर्नुहोस्"</string>
     <string name="no_connection_to_printer" msgid="2159246915977282728">"प्रिन्टरमा कुनै जडान छैन"</string>
     <string name="reason_unknown" msgid="5507940196503246139">"अज्ञात"</string>
     <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> प्रयोग गर्ने हो?"</string>
diff --git a/packages/PrintSpooler/res/values-pa/strings.xml b/packages/PrintSpooler/res/values-pa/strings.xml
index 00d895e..4ce8f97 100644
--- a/packages/PrintSpooler/res/values-pa/strings.xml
+++ b/packages/PrintSpooler/res/values-pa/strings.xml
@@ -30,12 +30,12 @@
     <string name="destination_default_text" msgid="5422708056807065710">"ਇੱਕ ਪ੍ਰਿੰਟਰ ਚੁਣੋ"</string>
     <string name="template_all_pages" msgid="3322235982020148762">"ਸਾਰੇ <xliff:g id="PAGE_COUNT">%1$s</xliff:g>"</string>
     <string name="template_page_range" msgid="428638530038286328">"<xliff:g id="PAGE_COUNT">%1$s</xliff:g> ਦੀ ਰੇਂਜ"</string>
-    <string name="pages_range_example" msgid="8558694453556945172">"ਉਦਾਹਰਨ ਲਈ 1—5,8,11—13"</string>
-    <string name="print_preview" msgid="8010217796057763343">"ਪ੍ਰਿੰਟ ਪ੍ਰੀਵਿਊ"</string>
-    <string name="install_for_print_preview" msgid="6366303997385509332">"ਪ੍ਰੀਵਿਊ ਲਈ PDF ਵਿਊਅਰ ਇੰਸਟੌਲ ਕਰੋ"</string>
+    <string name="pages_range_example" msgid="8558694453556945172">"ਉਦਾਹਰਨ ਵਜੋਂ 1—5,8,11—13"</string>
+    <string name="print_preview" msgid="8010217796057763343">"ਪ੍ਰਿੰਟ ਦੀ ਪੂਰਵ-ਝਲਕ"</string>
+    <string name="install_for_print_preview" msgid="6366303997385509332">"ਪੂਰਵ-ਝਲਕ ਲਈ PDF ਵਿਊਅਰ ਸਥਾਪਤ ਕਰੋ"</string>
     <string name="printing_app_crashed" msgid="854477616686566398">"ਪ੍ਰਿੰਟਿੰਗ ਐਪ ਕ੍ਰੈਸ਼ ਹੋਇਆ"</string>
     <string name="generating_print_job" msgid="3119608742651698916">"ਪ੍ਰਿੰਟ ਜੌਬ ਬਣਾ ਰਿਹਾ ਹੈ"</string>
-    <string name="save_as_pdf" msgid="5718454119847596853">"PDF ਦੇ ਤੌਰ ਤੇ ਰੱਖਿਅਤ ਕਰੋ"</string>
+    <string name="save_as_pdf" msgid="5718454119847596853">"PDF ਦੇ ਤੌਰ \'ਤੇ ਰੱਖਿਅਤ ਕਰੋ"</string>
     <string name="all_printers" msgid="5018829726861876202">"ਸਾਰੇ ਪ੍ਰਿੰਟਰ…"</string>
     <string name="print_dialog" msgid="32628687461331979">"ਪ੍ਰਿੰਟ ਡਾਇਲੌਗ"</string>
     <string name="current_page_template" msgid="5145005201131935302">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string>
@@ -49,10 +49,10 @@
     <string name="print_options_collapsed" msgid="7455930445670414332">"ਪ੍ਰਿੰਟ ਚੋਣਾਂ ਇਕੱਠਾ ਹੋਈਆਂ"</string>
     <string name="search" msgid="5421724265322228497">"ਖੋਜੋ"</string>
     <string name="all_printers_label" msgid="3178848870161526399">"ਸਾਰੇ ਪ੍ਰਿੰਟਰ"</string>
-    <string name="add_print_service_label" msgid="5356702546188981940">"ਸੇਵਾ ਜੋੜੋ"</string>
-    <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"ਖੋਜ ਬੌਕਸ ਦਿਖਾਇਆ"</string>
-    <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"ਖੋਜ ਬੌਕਸ ਲੁਕਾਇਆ"</string>
-    <string name="print_add_printer" msgid="1088656468360653455">"ਪ੍ਰਿੰਟਰ ਜੋੜੋ"</string>
+    <string name="add_print_service_label" msgid="5356702546188981940">"ਸੇਵਾ ਸ਼ਾਮਲ ਕਰੋ"</string>
+    <string name="print_search_box_shown_utterance" msgid="7967404953901376090">"ਖੋਜ ਬਾਕਸ ਦਿਖਾਇਆ"</string>
+    <string name="print_search_box_hidden_utterance" msgid="5727755169343113351">"ਖੋਜ ਬਾਕਸ ਲੁਕਾਇਆ"</string>
+    <string name="print_add_printer" msgid="1088656468360653455">"ਪ੍ਰਿੰਟਰ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="print_select_printer" msgid="7388760939873368698">"ਪ੍ਰਿੰਟਰ ਚੁਣੋ"</string>
     <string name="print_forget_printer" msgid="5035287497291910766">"ਪ੍ਰਿੰਟਰ ਭੁੱਲੋ"</string>
     <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
@@ -106,6 +106,6 @@
     <string name="print_error_default_message" msgid="8602678405502922346">"ਮਾਫ਼ ਕਰਨਾ, ਉਸਨੇ ਲਾਭਕਾਰੀ ਨਹੀਂ ਹੋਇਆ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="print_error_retry" msgid="1426421728784259538">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
     <string name="print_error_printer_unavailable" msgid="8985614415253203381">"ਇਹ ਪ੍ਰਿੰਟਰ ਇਸ ਵੇਲੇ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।"</string>
-    <string name="print_cannot_load_page" msgid="6179560924492912009">"ਝਲਕ ਨਹੀਂ ਵਿਖਾਈ ਜਾ ਸਕਦੀ"</string>
-    <string name="print_preparing_preview" msgid="3939930735671364712">"ਪ੍ਰੀਵਿਊ ਦੀ ਤਿਆਰੀ ਕਰ ਰਿਹਾ ਹੈ…"</string>
+    <string name="print_cannot_load_page" msgid="6179560924492912009">"ਪੂਰਵ-ਝਲਕ ਨਹੀਂ ਦਿਖਾਈ ਜਾ ਸਕਦੀ"</string>
+    <string name="print_preparing_preview" msgid="3939930735671364712">"ਪੂਰਵ-ਝਲਕ ਦੀ ਤਿਆਰੀ ਕਰ ਰਿਹਾ ਹੈ…"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-af/arrays.xml b/packages/SettingsLib/res/values-af/arrays.xml
index 53d5220..771abe6 100644
--- a/packages/SettingsLib/res/values-af/arrays.xml
+++ b/packages/SettingsLib/res/values-af/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Gebruik HDCP-kontrolering net vir DRM-inhoud"</item>
     <item msgid="45075631231212732">"Gebruik altyd HDCP-kontrolering"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (verstek)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Gebruik stelselkeuse (verstek)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-am/arrays.xml b/packages/SettingsLib/res/values-am/arrays.xml
index 039af7f..a5fb9cf 100644
--- a/packages/SettingsLib/res/values-am/arrays.xml
+++ b/packages/SettingsLib/res/values-am/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"ለDRM ይዘት ብቻ HDCP  ምልከታን ተጠቀም"</item>
     <item msgid="45075631231212732">"ሁልጊዜ የHDCP ምልከታ ተጠቀም"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (ነባሪ)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml
index bcbbcc6..603dcc8 100644
--- a/packages/SettingsLib/res/values-ar/arrays.xml
+++ b/packages/SettingsLib/res/values-ar/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"‏استخدام التحقق من HDCP لمحتوى DRM فقط"</item>
     <item msgid="45075631231212732">"‏استخدام التحقق من HDCP دومًا"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"‏AVRCP 1.4 (الافتراضي)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"استخدام اختيار النظام (افتراضي)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
index ba5968a..aaf67e7d 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Koristi HDCP proveru samo za DRM sadržaj"</item>
     <item msgid="45075631231212732">"Uvek koristi HDCP proveru"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (podrazumevano)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Koristi izbor sistema (podrazumevano)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-be/arrays.xml b/packages/SettingsLib/res/values-be/arrays.xml
index 7fc966a..ce5ca02 100644
--- a/packages/SettingsLib/res/values-be/arrays.xml
+++ b/packages/SettingsLib/res/values-be/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Выкарыстанне праверкі HDCP только для змесціва, абароненага DRM"</item>
     <item msgid="45075631231212732">"Заўсёды выкарыстоўваць праверку HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (стандартная)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Выбар сістэмы (стандартны)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml
index 3acd209..7eec6ed 100644
--- a/packages/SettingsLib/res/values-bg/arrays.xml
+++ b/packages/SettingsLib/res/values-bg/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Да се използва проверка с HDCP само за DRM съдържание"</item>
     <item msgid="45075631231212732">"Винаги да се използва проверка с HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (по подразбиране)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Използване на сист. избор (стандартно)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml
index 9dfc7fe..60869c4 100644
--- a/packages/SettingsLib/res/values-bn/arrays.xml
+++ b/packages/SettingsLib/res/values-bn/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"শুধুমাত্র DRM সামগ্রীর জন্য HDCP চেক করা ব্যবহার করুন"</item>
     <item msgid="45075631231212732">"সর্বদা HDCP পরীক্ষণ ব্যবহার করুন"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (ডিফল্ট)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index 10be7fe..c274d4c 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Koristi HDCP provjeru samo za DRM sadržaj"</item>
     <item msgid="45075631231212732">"Uvijek koristi HDCP provjeru"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (Zadano)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Koristi odabir sistema (Zadano)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml
index fce5e99..b163642 100644
--- a/packages/SettingsLib/res/values-ca/arrays.xml
+++ b/packages/SettingsLib/res/values-ca/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Utilitza la comprovació HDCP només per a contingut DRM"</item>
     <item msgid="45075631231212732">"Utilitza sempre la comprovació HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (predeterminada)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Utilitza selecció del sistema (predeterminada)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-cs/arrays.xml b/packages/SettingsLib/res/values-cs/arrays.xml
index 5776b84..9d665a3 100644
--- a/packages/SettingsLib/res/values-cs/arrays.xml
+++ b/packages/SettingsLib/res/values-cs/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Použít kontrolu HDCP pouze pro obsah DRM"</item>
     <item msgid="45075631231212732">"Vždy používat kontrolu HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (výchozí)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Použít systémový výběr (výchozí)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-da/arrays.xml b/packages/SettingsLib/res/values-da/arrays.xml
index 15c2514..0993d31 100644
--- a/packages/SettingsLib/res/values-da/arrays.xml
+++ b/packages/SettingsLib/res/values-da/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Brug kun HDCP-kontrol ved DRM-indhold"</item>
     <item msgid="45075631231212732">"Brug altid HDCP-kontrol"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (standard)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Brug systemvalg (standard)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-de/arrays.xml b/packages/SettingsLib/res/values-de/arrays.xml
index 1b9d25a..b5e3491 100644
--- a/packages/SettingsLib/res/values-de/arrays.xml
+++ b/packages/SettingsLib/res/values-de/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"HDCP-Prüfung nur für DRM-Inhalte verwenden"</item>
     <item msgid="45075631231212732">"HDCP-Prüfung immer verwenden"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (Standard)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Systemauswahl verwenden (Standard)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-el/arrays.xml b/packages/SettingsLib/res/values-el/arrays.xml
index 3794ce4..1b740e6 100644
--- a/packages/SettingsLib/res/values-el/arrays.xml
+++ b/packages/SettingsLib/res/values-el/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Χρήση ελέγχου HDCP μόνο για περιεχόμενο DRM"</item>
     <item msgid="45075631231212732">"Να χρησιμοποιείται πάντα έλεγχος HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (Προεπιλογή)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-en-rAU/arrays.xml b/packages/SettingsLib/res/values-en-rAU/arrays.xml
index 9abe5d9..f4fceae 100644
--- a/packages/SettingsLib/res/values-en-rAU/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rAU/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Use HDCP checking for DRM content only"</item>
     <item msgid="45075631231212732">"Always use HDCP checking"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (Default)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Use System Selection (Default)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-en-rCA/arrays.xml b/packages/SettingsLib/res/values-en-rCA/arrays.xml
index 9abe5d9..f4fceae 100644
--- a/packages/SettingsLib/res/values-en-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rCA/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Use HDCP checking for DRM content only"</item>
     <item msgid="45075631231212732">"Always use HDCP checking"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (Default)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Use System Selection (Default)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-en-rGB/arrays.xml b/packages/SettingsLib/res/values-en-rGB/arrays.xml
index 9abe5d9..f4fceae 100644
--- a/packages/SettingsLib/res/values-en-rGB/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rGB/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Use HDCP checking for DRM content only"</item>
     <item msgid="45075631231212732">"Always use HDCP checking"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (Default)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Use System Selection (Default)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-en-rIN/arrays.xml b/packages/SettingsLib/res/values-en-rIN/arrays.xml
index 9abe5d9..f4fceae 100644
--- a/packages/SettingsLib/res/values-en-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rIN/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Use HDCP checking for DRM content only"</item>
     <item msgid="45075631231212732">"Always use HDCP checking"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (Default)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Use System Selection (Default)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml
index f370f9e..16f725a 100644
--- a/packages/SettingsLib/res/values-es-rUS/arrays.xml
+++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Usar comprobación HDCP para contenido DRM solamente"</item>
     <item msgid="45075631231212732">"Siempre utilizar comprobación HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (predeterminado)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Usar selección del sistema (predeterminado)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml
index 22e4ac0..a752db9 100644
--- a/packages/SettingsLib/res/values-es/arrays.xml
+++ b/packages/SettingsLib/res/values-es/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Utilizar comprobación de HDCP solo para contenido DRM"</item>
     <item msgid="45075631231212732">"Utilizar siempre comprobación de HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (Predeterminada)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Usar preferencia del sistema (predeter.)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-et/arrays.xml b/packages/SettingsLib/res/values-et/arrays.xml
index 5b742d6..db796f1 100644
--- a/packages/SettingsLib/res/values-et/arrays.xml
+++ b/packages/SettingsLib/res/values-et/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Kasuta HDCP-kontrolli ainult DRM-sisu korral"</item>
     <item msgid="45075631231212732">"Kasuta alati HDCP-kontrollimist"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (vaikeseade)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Süsteemi valiku kasutamine (vaikeseade)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml
index 2d6aada..2436e79 100644
--- a/packages/SettingsLib/res/values-fa/arrays.xml
+++ b/packages/SettingsLib/res/values-fa/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"‏استفاده از بررسی HDCP فقط برای محتوای DRM"</item>
     <item msgid="45075631231212732">"‏همیشه از بررسی HDCP استفاده شود"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"‏AVRCP نسخه ۱.۴ (پیش‌فرض)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"‏avrcp نسخه ۱۴"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"استفاده از انتخاب سیستم (پیش‌فرض)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-fi/arrays.xml b/packages/SettingsLib/res/values-fi/arrays.xml
index 4eb9259..9ed0c89 100644
--- a/packages/SettingsLib/res/values-fi/arrays.xml
+++ b/packages/SettingsLib/res/values-fi/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Käytä HDCP-tarkistusta vain DRM-suojatulle sisällölle"</item>
     <item msgid="45075631231212732">"Käytä aina HDCP-tarkistusta"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (oletus)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Käytä järjestelmän valintaa (oletus)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-fr-rCA/arrays.xml b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
index 9d96f40..be568ed 100644
--- a/packages/SettingsLib/res/values-fr-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Utiliser la vérification HDCP uniquement pour le contenu GDN"</item>
     <item msgid="45075631231212732">"Toujours utiliser la vérification HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (par défaut)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Utiliser sélect. du système (par défaut)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-fr/arrays.xml b/packages/SettingsLib/res/values-fr/arrays.xml
index d2521f6..995a1ff 100644
--- a/packages/SettingsLib/res/values-fr/arrays.xml
+++ b/packages/SettingsLib/res/values-fr/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Utiliser la vérification HDCP uniquement pour le contenu DRM"</item>
     <item msgid="45075631231212732">"Toujours utiliser la vérification HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (par défaut)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Utiliser sélection système (par défaut)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index b53765b..f8cf107 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -377,8 +377,8 @@
     <string name="screen_zoom_summary_small" msgid="5867245310241621570">"Petit"</string>
     <string name="screen_zoom_summary_default" msgid="2247006805614056507">"Par défaut"</string>
     <string name="screen_zoom_summary_large" msgid="4835294730065424084">"Grand"</string>
-    <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Plus grand"</string>
-    <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Le plus grand"</string>
+    <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"Très grand"</string>
+    <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"Extrêmement grand"</string>
     <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"Personnalisé (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"Aide et commentaires"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
diff --git a/packages/SettingsLib/res/values-gl/arrays.xml b/packages/SettingsLib/res/values-gl/arrays.xml
index 9c6b9a9..d06fe9c 100644
--- a/packages/SettingsLib/res/values-gl/arrays.xml
+++ b/packages/SettingsLib/res/values-gl/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Utiliza a comprobación HDCP só para contido DRM"</item>
     <item msgid="45075631231212732">"Utilizar sempre a comprobación HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (predeterminado)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Usar selección sistema (predeterminado)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml
index d97767e..00eb29c 100644
--- a/packages/SettingsLib/res/values-gu/arrays.xml
+++ b/packages/SettingsLib/res/values-gu/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"ફક્ત DRM કન્ટેન્ટ માટે HDCP તપાસનો ઉપયોગ કરો"</item>
     <item msgid="45075631231212732">"હંમેશા HDCP તપાસનો ઉપયોગ કરો"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (ડિફૉલ્ટ)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-hr/arrays.xml b/packages/SettingsLib/res/values-hr/arrays.xml
index 7f1174d..ffc76e8 100644
--- a/packages/SettingsLib/res/values-hr/arrays.xml
+++ b/packages/SettingsLib/res/values-hr/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Upotrebljavaj HDCP provjeru samo za DRM sadržaj"</item>
     <item msgid="45075631231212732">"Uvijek upotrebljavaj HDCP provjeru"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (zadano)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Upotreba odabira sustava (zadano)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-hu/arrays.xml b/packages/SettingsLib/res/values-hu/arrays.xml
index 740b0cd..7ad170a 100644
--- a/packages/SettingsLib/res/values-hu/arrays.xml
+++ b/packages/SettingsLib/res/values-hu/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Csak DRM-tartalomhoz használjon HDCP ellenőrzést"</item>
     <item msgid="45075631231212732">"Mindig használjon HDCP ellenőrzést"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (alapértelmezett)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Rendszerérték (alapértelmezett)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml
index d552ea5..7406554 100644
--- a/packages/SettingsLib/res/values-hy/arrays.xml
+++ b/packages/SettingsLib/res/values-hy/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Օգտագործել HDCP-ը` միայն DRM-ի բովանդակությունը ստուգելու համար"</item>
     <item msgid="45075631231212732">"Միշտ օգտագործել HDCP ստուգումը"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (կանխադրված)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml
index b516a05..0e2217d 100644
--- a/packages/SettingsLib/res/values-in/arrays.xml
+++ b/packages/SettingsLib/res/values-in/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Gunakan pemeriksaan HDCP untuk konten DRM saja"</item>
     <item msgid="45075631231212732">"Selalu gunakan pemeriksaan HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (Default)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Gunakan Pilihan Sistem (Default)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-is/arrays.xml b/packages/SettingsLib/res/values-is/arrays.xml
index 33b2b72..a8a01a4 100644
--- a/packages/SettingsLib/res/values-is/arrays.xml
+++ b/packages/SettingsLib/res/values-is/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Nota HDCP-athugun aðeins fyrir höfundarréttarvarið efni"</item>
     <item msgid="45075631231212732">"Nota alltaf HDCP-eftirlit"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (sjálfgefið)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Nota val kerfisins (sjálfgefið)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-it/arrays.xml b/packages/SettingsLib/res/values-it/arrays.xml
index b235812..42a246d 100644
--- a/packages/SettingsLib/res/values-it/arrays.xml
+++ b/packages/SettingsLib/res/values-it/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Usa la verifica HDCP solo per contenuti DRM"</item>
     <item msgid="45075631231212732">"Usa sempre la verifica HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (predefinita)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Usa selezione di sistema (predefinita)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml
index 5daa1ef..b8197a8 100644
--- a/packages/SettingsLib/res/values-iw/arrays.xml
+++ b/packages/SettingsLib/res/values-iw/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"‏השתמש בבדיקת HDCP עבור תוכן DRM בלבד"</item>
     <item msgid="45075631231212732">"‏תמיד השתמש בבדיקת HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"‏AVRCP 1.4 (ברירת המחדל)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"שימוש בבחירת המערכת (ברירת המחדל)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml
index d2a59aa..aa20097 100644
--- a/packages/SettingsLib/res/values-ja/arrays.xml
+++ b/packages/SettingsLib/res/values-ja/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"DRMコンテンツにのみHDCPチェックを使用する"</item>
     <item msgid="45075631231212732">"HDCPチェックを常に使用する"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4(デフォルト)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"システムの選択(デフォルト)を使用"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ka/arrays.xml b/packages/SettingsLib/res/values-ka/arrays.xml
index b4fc19f..7e36f86 100644
--- a/packages/SettingsLib/res/values-ka/arrays.xml
+++ b/packages/SettingsLib/res/values-ka/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"HDCP შემოწმების გამოყენება მხოლოდ DRM კონტენტის შემთხვევაში"</item>
     <item msgid="45075631231212732">"ყოველთვის გამოიყენე HDCP შემოწმება"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (ნაგულისხმევი)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-kk/arrays.xml b/packages/SettingsLib/res/values-kk/arrays.xml
index 3037dc8..b0ba2ff 100644
--- a/packages/SettingsLib/res/values-kk/arrays.xml
+++ b/packages/SettingsLib/res/values-kk/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"HDCP (кең жолақты сандық мазмұн қорғау) тексеруді DRM (авторлық құқықты техникалық қорғау) мазмұны үшін ғана қолданыңыз"</item>
     <item msgid="45075631231212732">"Әрқашан HDCP (жоғары кең жолақты сандық мазмұн қорғаушы) тексерулерін қолданыңыз"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (әдепкі)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Жүйені таңдау (әдепкі)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-km/arrays.xml b/packages/SettingsLib/res/values-km/arrays.xml
index 85b927b..3cbdc37 100644
--- a/packages/SettingsLib/res/values-km/arrays.xml
+++ b/packages/SettingsLib/res/values-km/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"ប្រើ​ការ​ពិនិត្យ HDCP សម្រាប់​តែ​មាតិកា DRM ប៉ុណ្ណោះ"</item>
     <item msgid="45075631231212732">"ប្រើ​ការ​ពិនិត្យ HDCP ជា​និច្ច"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (លំនាំដើម)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"ប្រើ​ការ​ជ្រើសរើស​ប្រព័ន្ធ (លំនាំ​ដើម)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml
index 510cc7e..455b0a9 100644
--- a/packages/SettingsLib/res/values-kn/arrays.xml
+++ b/packages/SettingsLib/res/values-kn/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"DRM ವಿಷಯಗಳಿಗೆ ಮಾತ್ರ HDCP ಪರೀಕ್ಷಿಸುವಿಕೆಯನ್ನು ಬಳಸು"</item>
     <item msgid="45075631231212732">"HDCP ಪರಿಶೀಲನೆಯನ್ನು ಯಾವಾಗಲೂ ಬಳಸು"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (ಡಿಫಾಲ್ಟ್)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ko/arrays.xml b/packages/SettingsLib/res/values-ko/arrays.xml
index cf10624..3dbf759 100644
--- a/packages/SettingsLib/res/values-ko/arrays.xml
+++ b/packages/SettingsLib/res/values-ko/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"DRM 콘텐츠에 대해서만 HDCP 확인 사용"</item>
     <item msgid="45075631231212732">"항상 HDCP 확인 사용"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4(기본)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"시스템 설정 사용(기본)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml
index 28f00ab..721bfaa7 100644
--- a/packages/SettingsLib/res/values-ky/arrays.xml
+++ b/packages/SettingsLib/res/values-ky/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"HDCP текшерүү DRM мазмунуна гана колдонулсун"</item>
     <item msgid="45075631231212732">"Ар дайым HDCP текшерүү колдонулсун"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (Демейки)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Тутум тандаганды колдонуу (демейки)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-lo/arrays.xml b/packages/SettingsLib/res/values-lo/arrays.xml
index 4a11eec..6aa8ffc 100644
--- a/packages/SettingsLib/res/values-lo/arrays.xml
+++ b/packages/SettingsLib/res/values-lo/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"ໃຊ້ການກວດສອບ HDCP ສຳລັບເນື້ອຫາ DRM ເທົ່ານັ້ນ"</item>
     <item msgid="45075631231212732">"ໃຊ້ການກວດສອບ HDCP ສະເໝີ"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (Default)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Use System Selection (Default)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-lt/arrays.xml b/packages/SettingsLib/res/values-lt/arrays.xml
index 92a6c72..b4407ea 100644
--- a/packages/SettingsLib/res/values-lt/arrays.xml
+++ b/packages/SettingsLib/res/values-lt/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Taikyti HDCP tikrinimą tik DRM turiniui"</item>
     <item msgid="45075631231212732">"Visada naudoti HDCP tikrinimą"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (numatytoji)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Naudoti sistemos pasirink. (numatytasis)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-lv/arrays.xml b/packages/SettingsLib/res/values-lv/arrays.xml
index 9e73abe..09fc613 100644
--- a/packages/SettingsLib/res/values-lv/arrays.xml
+++ b/packages/SettingsLib/res/values-lv/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Izmantot HDCP pārbaudi tikai DRM saturam"</item>
     <item msgid="45075631231212732">"Vienmēr izmantot HDCP pārbaudi"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (noklusējuma)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Sistēmas atlases izmantošana (nokl.)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-mk/arrays.xml b/packages/SettingsLib/res/values-mk/arrays.xml
index 594c508..2d9d73ce 100644
--- a/packages/SettingsLib/res/values-mk/arrays.xml
+++ b/packages/SettingsLib/res/values-mk/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Користи ХДЦП проверка само за ДРМ содржина"</item>
     <item msgid="45075631231212732">"Секогаш користи ХДЦП проверка"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (Стандардно)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Користи избор на системот (стандардно)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml
index 359b758..121c287 100644
--- a/packages/SettingsLib/res/values-ml/arrays.xml
+++ b/packages/SettingsLib/res/values-ml/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"DRM ഉള്ളടക്കത്തിനുമാത്രമായി HDCP പരിശോധന ഉപയോഗിക്കുക"</item>
     <item msgid="45075631231212732">"എല്ലായ്‌പ്പോഴും HDCP പരിശോധന ഉപയോഗിക്കുക"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (ഡിഫോൾട്ട്)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ ‌(ഡിഫോൾട്ട്)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-mn/arrays.xml b/packages/SettingsLib/res/values-mn/arrays.xml
index 7c547bb..73f4099 100644
--- a/packages/SettingsLib/res/values-mn/arrays.xml
+++ b/packages/SettingsLib/res/values-mn/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"HDCP шалгахыг зөвхөн DRM контентэд ашиглах"</item>
     <item msgid="45075631231212732">"Байнга HDCP шалгахыг ашиглах"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (Өгөгдмөл)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml
index ed1c4e7..6064949 100644
--- a/packages/SettingsLib/res/values-mr/arrays.xml
+++ b/packages/SettingsLib/res/values-mr/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"केवळ DRM सामग्रीसाठी HDCP तपासणी वापरा"</item>
     <item msgid="45075631231212732">"नेहमी HDCP तपासणी वापरा"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (डीफॉल्ट)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"प्रणाली निवड वापरा (डीफॉल्ट)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 4386c8f..5e9ecdb 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -66,7 +66,7 @@
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"मीडिया ऑडिओ"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"फोन कॉल"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"फाइल स्थानांतरण"</string>
-    <string name="bluetooth_profile_hid" msgid="3680729023366986480">"इनपुट डीव्हाइस"</string>
+    <string name="bluetooth_profile_hid" msgid="3680729023366986480">"इनपुट डिव्हाइस"</string>
     <string name="bluetooth_profile_pan" msgid="3391606497945147673">"इंटरनेट अॅक्सेस"</string>
     <string name="bluetooth_profile_pbap" msgid="5372051906968576809">"संपर्क सामायिकरण"</string>
     <string name="bluetooth_profile_pbap_summary" msgid="6605229608108852198">"संपर्क सामायिकरणासाठी वापरा"</string>
@@ -182,7 +182,7 @@
     <string name="oem_unlock_enable" msgid="6040763321967327691">"OEM अनलॉक करणे"</string>
     <string name="oem_unlock_enable_summary" msgid="4720281828891618376">"बूटलोडर अनलॉक करण्यासाठी अनुमती द्या"</string>
     <string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"OEM अनलॉक करण्यास अनुमती द्यायची?"</string>
-    <string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"चेतावणी: हे सेटिंग चालू असताना या डीव्हाइस वर डीव्हाइस संरक्षण वैशिष्ट्ये काम करणार नाहीत."</string>
+    <string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"चेतावणी: हे सेटिंग चालू असताना या डिव्हाइस वर डिव्हाइस संरक्षण वैशिष्ट्ये काम करणार नाहीत."</string>
     <string name="mock_location_app" msgid="7966220972812881854">"बनावट स्थान अॅप निवडा"</string>
     <string name="mock_location_app_not_set" msgid="809543285495344223">"कोणताही बनावट स्थान अॅप सेट केला नाही"</string>
     <string name="mock_location_app_set" msgid="8966420655295102685">"बनावट स्थान अॅप: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
@@ -227,10 +227,10 @@
     <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"जरी वाय-फाय चालू असले तरीही, मोबाईल डेटा नेहमी चालू ठेवा (नेटवर्क जलदरीत्या स्विच करण्यासाठी)."</string>
     <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"उपलब्ध असल्यास टेदरिंग हार्डवेअर प्रवेग वापरा"</string>
     <string name="adb_warning_title" msgid="6234463310896563253">"USB डीबग करण्यास अनुमती द्यायची?"</string>
-    <string name="adb_warning_message" msgid="7316799925425402244">"USB डीबग करण्याचा हेतू फक्त विकास उद्देशांसाठी आहे. याचा वापर तुमचा कॉंप्युटर आणि तुमचे डीव्हाइस यांच्या दरम्यान डेटा कॉपी करण्यासाठी करा, सूचनेशिवाय तुमच्या डीव्हाइस वर अॅप्स इंस्टॉल करा आणि लॉग डेटा वाचा."</string>
+    <string name="adb_warning_message" msgid="7316799925425402244">"USB डीबग करण्याचा हेतू फक्त विकास उद्देशांसाठी आहे. याचा वापर तुमचा कॉंप्युटर आणि तुमचे डिव्हाइस यांच्या दरम्यान डेटा कॉपी करण्यासाठी करा, सूचनेशिवाय तुमच्या डिव्हाइस वर अॅप्स इंस्टॉल करा आणि लॉग डेटा वाचा."</string>
     <string name="adb_keys_warning_message" msgid="5659849457135841625">"आपण पूर्वी अॉथोराइझ केलेल्या सर्व संगणकांवरुन USB डीबग करण्यासाठी अॅक्सेस रीव्होक करायचा?"</string>
     <string name="dev_settings_warning_title" msgid="7244607768088540165">"विकास सेटिंग्जला अनुमती द्यायची?"</string>
-    <string name="dev_settings_warning_message" msgid="2298337781139097964">"या सेटिंग्जचा हेतू फक्त विकास वापरासाठी आहे. त्यामुळे तुमचे डीव्हाइस आणि त्यावरील अॅप्लिकेशन ब्रेक होऊ शकतात किंवा नेहमीपेक्षा वेगळे वर्तन करू शकतात."</string>
+    <string name="dev_settings_warning_message" msgid="2298337781139097964">"या सेटिंग्जचा हेतू फक्त विकास वापरासाठी आहे. त्यामुळे तुमचे डिव्हाइस आणि त्यावरील अॅप्लिकेशन ब्रेक होऊ शकतात किंवा नेहमीपेक्षा वेगळे वर्तन करू शकतात."</string>
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB वर अॅप्स पडताळून पाहा"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"हानिकारक वर्तनासाठी ADB/ADT द्वारे इंस्टॉल अॅप्स तपासा."</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"नावांशिवाय ब्‍लूटूथ डीव्‍हाइस (फक्‍त MAC पत्‍ते) दाखवले जातील"</string>
@@ -368,9 +368,9 @@
     <string name="install_other_apps" msgid="6986686991775883017">"अज्ञात अ‍ॅप्स इंस्टॉल करा"</string>
     <string name="home" msgid="3256884684164448244">"सेटिंग्ज होम"</string>
   <string-array name="battery_labels">
-    <item msgid="8494684293649631252">"0%"</item>
-    <item msgid="8934126114226089439">"50%"</item>
-    <item msgid="1286113608943010849">"100%"</item>
+    <item msgid="8494684293649631252">"०%"</item>
+    <item msgid="8934126114226089439">"५०%"</item>
+    <item msgid="1286113608943010849">"१००%"</item>
   </string-array>
     <string name="charge_length_format" msgid="8978516217024434156">"<xliff:g id="ID_1">%1$s</xliff:g> पूर्वी"</string>
     <string name="remaining_length_format" msgid="7886337596669190587">"<xliff:g id="ID_1">%1$s</xliff:g> शिल्लक"</string>
@@ -386,7 +386,7 @@
     <string name="retail_demo_reset_next" msgid="8356731459226304963">"पुढील"</string>
     <string name="retail_demo_reset_title" msgid="696589204029930100">"संकेतशब्द आवश्यक"</string>
     <string name="active_input_method_subtypes" msgid="3596398805424733238">"सक्रिय इनपुट पद्धती"</string>
-    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"सिस्टीम भाषा वापरा"</string>
+    <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"सिस्टम भाषा वापरा"</string>
     <string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> साठी सेटिंग्ज उघडण्यात अयशस्वी"</string>
     <string name="ime_security_warning" msgid="4135828934735934248">"ही इनपुट पद्धत संकेतशब्द आणि क्रेडिट कार्ड नंबर यासह, आपण टाइप करता तो सर्व मजकूर संकलित करण्यात सक्षम होऊ शकते. ही <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> अॅपवरून येते. ही इनपुट पद्धत वापरायची?"</string>
     <string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"टीप: रीबूट केल्यानंतर, तुम्ही आपला फोन अनलॉक करे पर्यंत हे अॅप सुरू होऊ शकत नाही"</string>
diff --git a/packages/SettingsLib/res/values-ms/arrays.xml b/packages/SettingsLib/res/values-ms/arrays.xml
index f4942aa..915814f 100644
--- a/packages/SettingsLib/res/values-ms/arrays.xml
+++ b/packages/SettingsLib/res/values-ms/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Gunakan penyemakan HDCP untuk kandungan DRM sahaja"</item>
     <item msgid="45075631231212732">"Sentiasa gunakan penyemakan HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (Lalai)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Gunakan Pilihan Sistem (Lalai)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml
index f2bb760..1882e2e 100644
--- a/packages/SettingsLib/res/values-nb/arrays.xml
+++ b/packages/SettingsLib/res/values-nb/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Bruk HDCP-kontroll kun for DRM-innhold"</item>
     <item msgid="45075631231212732">"Bruk alltid HDCP-kontroll"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (standard)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Bruk systemvalg (standard)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index b5a19de..de6b86e 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"DRM सामग्रीको लागि मात्र HDCP जाँचको प्रयोग गर्नुहोस्"</item>
     <item msgid="45075631231212732">"सधैँ HDCP जाँच प्रयोग गर्नुहोस्"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP १.४ (पूर्वनिर्धारित)"</item>
+    <item msgid="2809759619990248160">"AVRCP १.३"</item>
+    <item msgid="6199178154704729352">"AVRCP १.५"</item>
+    <item msgid="5172170854953034852">"AVRCP १.६"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp १३"</item>
+    <item msgid="8837606198371920819">"avrcp १५"</item>
+    <item msgid="3422726142222090896">"avrcp १६"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-pa/arrays.xml b/packages/SettingsLib/res/values-pa/arrays.xml
index 7a50cb9..750aee0 100644
--- a/packages/SettingsLib/res/values-pa/arrays.xml
+++ b/packages/SettingsLib/res/values-pa/arrays.xml
@@ -50,7 +50,7 @@
   </string-array>
   <string-array name="hdcp_checking_titles">
     <item msgid="441827799230089869">"ਕਦੇ ਵੀ ਜਾਂਚ ਨਾ ਕਰੋ"</item>
-    <item msgid="6042769699089883931">"ਕੇਵਲ DRM ਸਮੱਗਰੀ ਲਈ ਜਾਂਚ ਕਰੋ"</item>
+    <item msgid="6042769699089883931">"ਸਿਰਫ਼ DRM ਸਮੱਗਰੀ ਲਈ ਜਾਂਚ ਕਰੋ"</item>
     <item msgid="9174900380056846820">"ਹਮੇਸ਼ਾਂ ਜਾਂਚ ਕਰੋ"</item>
   </string-array>
   <string-array name="hdcp_checking_summaries">
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"ਕੇਵਲ DRM ਸਮੱਗਰੀ ਲਈ HDCP ਜਾਂਚ"</item>
     <item msgid="45075631231212732">"ਹਮੇਸਾਂ HDCP ਜਾਂਚ ਵਰਤੋ"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
@@ -216,7 +222,7 @@
   <string-array name="show_non_rect_clip_entries">
     <item msgid="993742912147090253">"ਬੰਦ"</item>
     <item msgid="675719912558941285">"ਨੀਲੇ ਵਿੱਚ ਗ਼ੈਰ-ਆਇਤਾਕਾਰ ਕਲਿਪ ਖੇਤਰ ਡ੍ਰਾ ਕਰੋ"</item>
-    <item msgid="1064373276095698656">"ਹਾਈਲਾਈਟ ਜਾਂਚ ਕੀਤੀਆਂ ਡ੍ਰਾਇੰਗ ਕਮਾਂਡਾਂ ਹਰੇ ਵਿੱਚ ਹਨ"</item>
+    <item msgid="1064373276095698656">"ਜਾਂਚ ਕੀਤੀਆਂ ਡ੍ਰਾਇੰਗ ਕਮਾਂਡਾਂ ਹਰੇ ਵਿੱਚ ਉਜਾਗਰ ਕਰੋ"</item>
   </string-array>
   <string-array name="track_frame_time_entries">
     <item msgid="2193584639058893150">"ਬੰਦ"</item>
@@ -243,7 +249,7 @@
   <string-array name="usb_configuration_titles">
     <item msgid="488237561639712799">"ਚਾਰਜਿੰਗ"</item>
     <item msgid="5220695614993094977">"MTP (ਮੀਡੀਆ ਟ੍ਰਾਂਸਫਰ ਪ੍ਰੋਟੋਕੋਲ)"</item>
-    <item msgid="2086000968159047375">"PTP (ਤਸਵੀਰ ਟ੍ਰਾਂਸਫਰ ਪ੍ਰੋਟੋਕੋਲ)"</item>
+    <item msgid="2086000968159047375">"PTP (ਪਿਕਚਰ ਟ੍ਰਾਂਸਫਰ ਪ੍ਰੋਟੋਕੋਲ)"</item>
     <item msgid="7398830860950841822">"RNDIS (USB ਈਥਰਨੈਟ)"</item>
     <item msgid="1718924214939774352">" ਆਡੀਓ  ਸਰੋਤ"</item>
     <item msgid="8126315616613006284">"MIDI"</item>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index a825b07..6e93e869 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -30,13 +30,13 @@
     <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"ਪ੍ਰਮਾਣੀਕਰਨ ਸਮੱਸਿਆ"</string>
     <string name="wifi_cant_connect" msgid="5410016875644565884">"ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
     <string name="wifi_cant_connect_to_ap" msgid="1222553274052685331">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\' ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
-    <string name="wifi_check_password_try_again" msgid="516958988102584767">"ਪਾਸਵਰਡ ਜਾਂਚੋ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
+    <string name="wifi_check_password_try_again" msgid="516958988102584767">"ਪਾਸਵਰਡ ਦੀ ਜਾਂਚ ਕਰੋ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
     <string name="wifi_not_in_range" msgid="1136191511238508967">"ਰੇਂਜ ਵਿੱਚ ਨਹੀਂ ਹੈ"</string>
     <string name="wifi_no_internet_no_reconnect" msgid="5724903347310541706">"ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ"</string>
     <string name="wifi_no_internet" msgid="3880396223819116454">"ਕੋਈ ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ ਨਹੀਂ"</string>
     <string name="saved_network" msgid="4352716707126620811">"<xliff:g id="NAME">%1$s</xliff:g> ਵੱਲੋਂ ਸੁਰੱਖਿਅਤ ਕੀਤਾ"</string>
     <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s ਰਾਹੀਂ ਆਪਣੇ-ਆਪ ਕਨੈਕਟ ਹੋਇਆ"</string>
-    <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"ਨੈੱਟਵਰਕ ਰੇਟਿੰਗ ਪ੍ਰਦਾਨਕ ਰਾਹੀਂ ਆਪਣੇ-ਆਪ ਕਨੈਕਟ ਹੋਇਆ"</string>
+    <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"ਨੈੱਟਵਰਕ ਰੇਟਿੰਗ ਪ੍ਰਦਾਨਕ ਰਾਹੀਂ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਕਨੈਕਟ ਹੋਇਆ"</string>
     <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s ਰਾਹੀਂ ਕਨੈਕਟ ਕੀਤਾ"</string>
     <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s ਰਾਹੀਂ ਉਪਲਬਧ"</string>
     <string name="wifi_connected_no_internet" msgid="3149853966840874992">"ਕਨੈਕਟ ਕੀਤਾ, ਕੋਈ ਇੰਟਰਨੈੱਟ ਨਹੀਂ"</string>
@@ -55,14 +55,14 @@
     <string name="bluetooth_connecting" msgid="8555009514614320497">"ਕਨੈਕਟ ਕਰ ਰਿਹਾ ਹੈ…"</string>
     <string name="bluetooth_connected" msgid="6038755206916626419">"ਕਨੈਕਟ ਕੀਤਾ"</string>
     <string name="bluetooth_pairing" msgid="1426882272690346242">"ਪੇਅਰ ਕਰ ਰਿਹਾ ਹੈ…"</string>
-    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"ਕਨੈਕਟ ਕੀਤਾ (ਕੋਈ ਫੋਨ ਨਹੀਂ)"</string>
+    <string name="bluetooth_connected_no_headset" msgid="2866994875046035609">"ਕਨੈਕਟ ਕੀਤਾ (ਕੋਈ ਫ਼ੋਨ ਨਹੀਂ)"</string>
     <string name="bluetooth_connected_no_a2dp" msgid="4576188601581440337">"ਕਨੈਕਟ ਕੀਤਾ (ਕੋਈ ਮੀਡੀਆ ਨਹੀਂ)"</string>
     <string name="bluetooth_connected_no_map" msgid="6504436917057479986">"ਕਨੈਕਟ ਕੀਤਾ (ਕੋਈ ਸੁਨੇਹਾ ਪਹੁੰਚ ਨਹੀਂ)"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"ਕਨੈਕਟ ਕੀਤਾ (ਕੋਈ ਫੋਨ ਜਾਂ ਮੀਡੀਆ ਨਹੀਂ)"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp" msgid="9195757766755553810">"ਕਨੈਕਟ ਕੀਤਾ (ਕੋਈ ਫ਼ੋਨ ਜਾਂ ਮੀਡੀਆ ਨਹੀਂ)"</string>
     <string name="bluetooth_connected_battery_level" msgid="7049181126136692368">"ਕਨੈਕਟ ਕੀਤੀ ਗਈ, ਬੈਟਰੀ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"ਕਨੈਕਟ ਕੀਤੀ ਗਈ (ਕੋਈ ਫ਼ੋਨ ਨਹੀਂ), ਬੈਟਰੀ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="5504193961248406027">"ਕਨੈਕਟ ਕੀਤਾ (ਕੋਈ ਫ਼ੋਨ ਨਹੀਂ), ਬੈਟਰੀ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="4751724026365870779">"ਕਨੈਕਟ ਕੀਤੀ ਗਈ (ਕੋਈ ਮੀਡੀਆ ਨਹੀਂ), ਬੈਟਰੀ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"ਕਨੈਕਟ ਕੀਤੀ ਗਈ (ਕੋਈ ਫ਼ੋਨ ਜਾਂ ਮੀਡੀਆ ਨਹੀਂ), ਬੈਟਰੀ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="1549265779323455261">"ਕਨੈਕਟ ਕੀਤਾ (ਕੋਈ ਫ਼ੋਨ ਜਾਂ ਮੀਡੀਆ ਨਹੀਂ), ਬੈਟਰੀ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp" msgid="2031475486179830674">"ਮੀਡੀਆ  ਆਡੀਓ"</string>
     <string name="bluetooth_profile_headset" msgid="7815495680863246034">"ਫ਼ੋਨ ਕਾਲਾਂ"</string>
     <string name="bluetooth_profile_opp" msgid="9168139293654233697">"ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ"</string>
@@ -76,11 +76,11 @@
     <string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ਆਡੀਓ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
     <string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ਆਡੀਓ"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"ਮੀਡੀਆ  ਆਡੀਓ  ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
-    <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ਫੋਨ  ਆਡੀਓ  ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
-    <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ ਸਰਵਰ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
+    <string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ਫ਼ੋਨ ਔਡੀਓ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
+    <string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ਫਾਈਲ ਟ੍ਰਾਂਸਫ਼ਰ ਸਰਵਰ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
     <string name="bluetooth_map_profile_summary_connected" msgid="8191407438851351713">"ਨਕਸ਼ੇ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
     <string name="bluetooth_sap_profile_summary_connected" msgid="8561765057453083838">"SAP ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
-    <string name="bluetooth_opp_profile_summary_not_connected" msgid="1267091356089086285">"ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ ਸਰਵਰ ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ"</string>
+    <string name="bluetooth_opp_profile_summary_not_connected" msgid="1267091356089086285">"ਫਾਈਲ ਟ੍ਰਾਂਸਫ਼ਰ ਸਰਵਰ ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ"</string>
     <string name="bluetooth_hid_profile_summary_connected" msgid="3381760054215168689">"ਇਨਪੁੱਟ ਡੀਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
     <string name="bluetooth_pan_user_profile_summary_connected" msgid="4602294638909590612">"ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ ਲਈ ਡੀਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
     <string name="bluetooth_pan_nap_profile_summary_connected" msgid="1561383706411975199">"ਡੀਵਾਈਸ ਨਾਲ ਸਥਾਨਕ ਇੰਟਰਨੈੱਟ ਕਨੈਕਸ਼ਨ ਸਾਂਝਾ ਕਰ ਰਿਹਾ ਹੈ"</string>
@@ -88,7 +88,7 @@
     <string name="bluetooth_map_profile_summary_use_for" msgid="5154200119919927434">"ਨਕਸ਼ੇ ਲਈ ਵਰਤੋ"</string>
     <string name="bluetooth_sap_profile_summary_use_for" msgid="7085362712786907993">"ਸਿਮ ਪਹੁੰਚ ਲਈ ਵਰਤੋ"</string>
     <string name="bluetooth_a2dp_profile_summary_use_for" msgid="4630849022250168427">"ਮੀਡੀਆ  ਆਡੀਓ  ਲਈ ਵਰਤੋ"</string>
-    <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ਫੋਨ  ਆਡੀਓ  ਲਈ ਵਰਤੋ"</string>
+    <string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ਫ਼ੋਨ ਔਡੀਓ ਲਈ ਵਰਤੋ"</string>
     <string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ ਲਈ ਵਰਤੋ"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ਇਨਪੁਟ ਲਈ ਵਰਤੋ"</string>
     <string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ਪੇਅਰ ਕਰੋ"</string>
@@ -122,7 +122,7 @@
     <string name="launch_defaults_some" msgid="313159469856372621">"ਕੁਝ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਸੈੱਟ ਕੀਤੇ"</string>
     <string name="launch_defaults_none" msgid="4241129108140034876">"ਕੋਈ ਡਿਫੌਲਟਸ ਸੈਟ ਨਹੀਂ ਕੀਤੇ"</string>
     <string name="tts_settings" msgid="8186971894801348327">"ਲਿਖਤ ਤੋਂ ਬੋਲੀ ਸੈਟਿੰਗਾਂ"</string>
-    <string name="tts_settings_title" msgid="1237820681016639683">"ਲਿਖਤ-ਤੋਂ-ਬੋਲੀ ਆਊਟਪੁੱਟ"</string>
+    <string name="tts_settings_title" msgid="1237820681016639683">"ਲਿਖਤ ਤੋਂ ਬੋਲੀ ਆਊਟਪੁਟ"</string>
     <string name="tts_default_rate_title" msgid="6030550998379310088">"ਸਪੀਚ ਰੇਟ"</string>
     <string name="tts_default_rate_summary" msgid="4061815292287182801">"ਸਪੀਡ ਜਿਸਤੇ ਟੈਕਸਟ ਬੋਲਿਆ ਜਾਂਦਾ ਹੈ"</string>
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"ਪਿਚ"</string>
@@ -133,10 +133,10 @@
     <string name="tts_default_lang_summary" msgid="5219362163902707785">"ਬੋਲੇ ਗਏ ਟੈਕਸਟ ਲਈ ਭਾਸ਼ਾ-ਵਿਸ਼ੇਸ਼ ਵੌਇਸ ਸੈਟ ਕਰਦਾ ਹੈ"</string>
     <string name="tts_play_example_title" msgid="7094780383253097230">"ਇੱਕ ਉਦਾਹਰਨ ਲਈ ਸੁਣੋ"</string>
     <string name="tts_play_example_summary" msgid="8029071615047894486">"ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਦਾ ਇੱਕ ਛੋਟਾ ਪ੍ਰਦਰਸ਼ਨ ਪਲੇ ਕਰੋ"</string>
-    <string name="tts_install_data_title" msgid="4264378440508149986">"ਵੌਇਸ  ਡਾਟਾ  ਇੰਸਟੌਲ ਕਰੋ"</string>
-    <string name="tts_install_data_summary" msgid="5742135732511822589">"ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਲਈ ਲੁੜੀਂਦਾ ਵੌਇਸ  ਡਾਟਾ  ਇੰਸਟੌਲ ਕਰੋ"</string>
+    <string name="tts_install_data_title" msgid="4264378440508149986">"ਵੌਇਸ ਡਾਟਾ ਸਥਾਪਤ ਕਰੋ"</string>
+    <string name="tts_install_data_summary" msgid="5742135732511822589">"ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਲਈ ਲੋੜੀਂਦਾ ਵੌਇਸ ਡਾਟਾ ਸਥਾਪਤ ਕਰੋ"</string>
     <string name="tts_engine_security_warning" msgid="8786238102020223650">"ਇਹ ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਇੰਜਣ ਉਹ ਸਭ ਲਿਖਤ ਇਕੱਤਰ ਕਰਨ ਵਿੱਚ ਸਮਰੱਥ ਹੋ ਸਕਦਾ ਹੈ, ਜੋ ਬੋਲਿਆ ਜਾਏਗਾ, ਨਿੱਜੀ ਡਾਟਾ ਸਮੇਤ ਜਿਵੇਂ ਪਾਸਵਰਡ ਅਤੇ ਕ੍ਰੈਡਿਟ ਕਾਰਡ ਨੰਬਰ। ਇਹ <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g> ਇੰਜਣ ਤੋਂ ਆਉਂਦਾ ਹੈ। ਕੀ ਇਸ ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਇੰਜਣ ਦੀ ਵਰਤੋਂ ਨੂੰ ਚਾਲੂ ਕਰਨਾ ਹੈੈ?"</string>
-    <string name="tts_engine_network_required" msgid="1190837151485314743">"ਇਸ ਭਾਸ਼ਾ ਲਈ ਟੈਕਸਟ-ਟੂ-ਸਪੀਚ ਆਊਟਪੁਟ ਲਈ ਇੱਕ ਚਾਲੂ ਨੈੱਟਵਰਕ ਕਨੈਕਸ਼ਨ ਦੀ ਲੋੜ ਹੈ।"</string>
+    <string name="tts_engine_network_required" msgid="1190837151485314743">"ਇਸ ਭਾਸ਼ਾ ਲਈ ਲਿਖਤ ਤੋਂ ਬੋਲੀ ਆਊਟਪੁੱਟ ਲਈ ਇੱਕ ਚਾਲੂ ਨੈੱਟਵਰਕ ਕਨੈਕਸ਼ਨ ਦੀ ਲੋੜ ਹੈ।"</string>
     <string name="tts_default_sample_string" msgid="4040835213373086322">"ਇਹ ਸਪੀਚ ਸਿੰਥੈਸਿਸ ਦਾ ਇੱਕ ਉਦਾਹਰਨ ਹੈ"</string>
     <string name="tts_status_title" msgid="7268566550242584413">"ਪੂਰਵ-ਨਿਰਧਾਰਤ ਭਾਸ਼ਾ ਸਥਿਤੀ"</string>
     <string name="tts_status_ok" msgid="1309762510278029765">"<xliff:g id="LOCALE">%1$s</xliff:g> ਪੂਰੀ ਤਰ੍ਹਾਂ ਸਮਰਥਿਤ ਹੈ"</string>
@@ -163,31 +163,31 @@
     <string name="choose_profile" msgid="6921016979430278661">"ਪ੍ਰੋਫਾਈਲ ਚੁਣੋ"</string>
     <string name="category_personal" msgid="1299663247844969448">"ਨਿੱਜੀ"</string>
     <string name="category_work" msgid="8699184680584175622">"ਦਫ਼ਤਰ"</string>
-    <string name="development_settings_title" msgid="215179176067683667">"ਵਿਕਾਸਕਾਰ ਚੋਣਾਂ"</string>
-    <string name="development_settings_enable" msgid="542530994778109538">"ਵਿਕਾਸਕਾਰ ਚੋਣਾਂ ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
+    <string name="development_settings_title" msgid="215179176067683667">"ਵਿਕਾਸਕਾਰ ਵਿਕਲਪ"</string>
+    <string name="development_settings_enable" msgid="542530994778109538">"ਵਿਕਾਸਕਾਰ ਵਿਕਲਪਾਂ ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
     <string name="development_settings_summary" msgid="1815795401632854041">"ਐਪ ਵਿਕਾਸ ਲਈ ਚੋਣਾਂ ਸੈੱਟ ਕਰੋ"</string>
-    <string name="development_settings_not_available" msgid="4308569041701535607">"ਇਸ ਉਪਭੋਗਤਾ ਲਈ ਵਿਕਾਸਕਾਰ ਚੋਣਾਂ ਉਪਲਬਧ ਨਹੀਂ ਹਨ"</string>
+    <string name="development_settings_not_available" msgid="4308569041701535607">"ਇਸ ਵਰਤੋਂਕਾਰ ਲਈ ਵਿਕਾਸਕਾਰ ਵਿਕਲਪ ਉਪਲਬਧ ਨਹੀਂ ਹਨ"</string>
     <string name="vpn_settings_not_available" msgid="956841430176985598">"ਇਸ ਵਰਤੋਂਕਾਰ ਲਈ VPN ਸੈਟਿੰਗਾਂ ਉਪਲਬਧ ਨਹੀਂ ਹਨ"</string>
     <string name="tethering_settings_not_available" msgid="6765770438438291012">"ਇਸ ਵਰਤੋਂਕਾਰ ਲਈ ਟੈਦਰਿੰਗ ਸੈਟਿੰਗਾਂ ਉਪਲਬਧ ਨਹੀਂ ਹਨ"</string>
     <string name="apn_settings_not_available" msgid="7873729032165324000">"ਐਕਸੈੱਸ ਪੁਆਇੰਟ ਨਾਮ ਸੈਟਿੰਗਾਂ ਇਸ ਵਰਤੋਂਕਾਰ ਲਈ ਉਪਲਬਧ ਨਹੀਂ ਹਨ"</string>
     <string name="enable_adb" msgid="7982306934419797485">"USB ਡੀਬਗਿੰਗ"</string>
-    <string name="enable_adb_summary" msgid="4881186971746056635">"ਡੀਬਗ ਮੋਡ ਜਦੋਂ USB ਕਨੈਕਟ ਕੀਤੀ ਜਾਏ"</string>
+    <string name="enable_adb_summary" msgid="4881186971746056635">"ਡੀਬੱਗ ਮੋਡ ਜਦੋਂ USB ਕਨੈਕਟ ਕੀਤੀ ਜਾਏ"</string>
     <string name="clear_adb_keys" msgid="4038889221503122743">"USB ਡੀਬਗਿੰਗ ਅਧਿਕਾਰ ਰੱਦ ਕਰੋ"</string>
     <string name="bugreport_in_power" msgid="7923901846375587241">"ਬੱਗ ਰਿਪੋਰਟ ਸ਼ਾਰਟਕੱਟ"</string>
     <string name="bugreport_in_power_summary" msgid="1778455732762984579">"ਇੱਕ ਬੱਗ ਰਿਪੋਰਟ ਲੈਣ ਲਈ ਪਾਵਰ ਮੀਨੂ ਵਿੱਚ ਇੱਕ ਬਟਨ ਦਿਖਾਓ"</string>
     <string name="keep_screen_on" msgid="1146389631208760344">"ਸਕਿਰਿਆ ਰੱਖੋ"</string>
     <string name="keep_screen_on_summary" msgid="2173114350754293009">"ਸਕ੍ਰੀਨ ਚਾਰਜਿੰਗ ਦੇ ਸਮੇਂ ਕਦੇ ਵੀ ਸਲੀਪ ਨਹੀਂ ਹੋਵੇਗੀ"</string>
-    <string name="bt_hci_snoop_log" msgid="3340699311158865670">"Bluetooth HCI ਸਨੂਪ ਲੌਗ ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
+    <string name="bt_hci_snoop_log" msgid="3340699311158865670">"ਬਲੂਟੁੱਥ HCI ਸਨੂਪ ਲੌਗ ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
     <string name="bt_hci_snoop_log_summary" msgid="730247028210113851">"ਇੱਕ ਫਾਈਲ ਵਿੱਚ ਸਾਰੇ bluetooth HCI ਪੈਕੇਟ ਕੈਪਚਰ ਕਰੋ"</string>
     <string name="oem_unlock_enable" msgid="6040763321967327691">"OEM ਅਣਲਾਕ ਕਰਨਾ"</string>
-    <string name="oem_unlock_enable_summary" msgid="4720281828891618376">"ਬੂਟਲੋਡਰ ਨੂੰ ਅਨਲੌਕ ਕੀਤੇ ਜਾਣ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
+    <string name="oem_unlock_enable_summary" msgid="4720281828891618376">"ਬੂਟਲੋਡਰ ਨੂੰ ਅਣਲਾਕ ਕੀਤੇ ਜਾਣ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
     <string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"ਕੀ OEM ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
     <string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"ਚਿਤਾਵਨੀ: ਡੀਵਾਈਸ ਸੁਰੱਖਿਆ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਉਦੋਂ ਇਸ ਡੀਵਾਈਸ ਤੇ ਕੰਮ ਨਹੀਂ ਕਰਨਗੀਆਂ ਜਦੋਂ ਇਹ ਸੈਟਿੰਗ ਚਾਲੂ ਹੋਵੇਗੀ।"</string>
     <string name="mock_location_app" msgid="7966220972812881854">"ਮੌਕ ਸਥਾਨ ਐਪ ਚੁਣੋ"</string>
     <string name="mock_location_app_not_set" msgid="809543285495344223">"ਕੋਈ ਵੀ ਮੌਕ ਸਥਾਨ ਐਪ ਸੈੱਟ ਨਹੀਂ ਕੀਤੀ ਗਈ"</string>
     <string name="mock_location_app_set" msgid="8966420655295102685">"ਮੌਕ ਸਥਾਨ ਐਪ: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="debug_networking_category" msgid="7044075693643009662">"ਨੈੱਟਵਰਕਿੰਗ"</string>
-    <string name="wifi_display_certification" msgid="8611569543791307533">"ਵਾਇਰਲੈਸ ਡਿਸਪਲੇ ਪ੍ਰਮਾਣੀਕਰਨ"</string>
+    <string name="wifi_display_certification" msgid="8611569543791307533">"ਵਾਇਰਲੈੱਸ ਡਿਸਪਲੇ ਪ੍ਰਮਾਣੀਕਰਨ"</string>
     <string name="wifi_verbose_logging" msgid="4203729756047242344">"ਵਾਈ-ਫਾਈ ਵਰਬੋਸ ਲੌਗਿੰਗ ਚਾਲੂ ਕਰੋ"</string>
     <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ਆਕਰਮਣਸ਼ੀਲ ਵਾਈ‑ਫਾਈ ਤੋਂ ਮੋਬਾਈਲ ਹੈਂਡਓਵਰ"</string>
     <string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ਹਮੇਸ਼ਾਂ ਵਾਈ‑ਫਾਈ ਰੋਮ ਸਕੈਨਾਂ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
@@ -209,7 +209,7 @@
     <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"ਬਲੂਟੁੱਥ ਔਡੀਓ LDAC ਕੋਡੇਕ: ਪਲੇਬੈਕ ਗੁਣਵੱਤਾ"</string>
     <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"ਬਲੂਟੁੱਥ ਔਡੀਓ LDAC ਕੋਡੇਕ ਚੁਣੋ:\nਪਲੇਬੈਕ ਗੁਣਵੱਤਾ"</string>
     <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"ਸਟ੍ਰੀਮਿੰਗ: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
-    <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ਵਾਇਰਲੈਸ ਡਿਸਪਲੇ ਪ੍ਰਮਾਣੀਕਰਨ ਲਈ ਚੋਣਾਂ ਦਿਖਾਓ"</string>
+    <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ਵਾਇਰਲੈੱਸ ਡਿਸਪਲੇ ਪ੍ਰਮਾਣੀਕਰਨ ਲਈ ਚੋਣਾਂ ਪ੍ਰਦਰਸ਼ਿਤ ਕਰੋ"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ਵਾਈ‑ਫਾਈ ਲੌਗਿੰਗ ਪੱਧਰ ਵਧਾਓ, ਵਾਈ‑ਫਾਈ Picker ਵਿੱਚ ਪ੍ਰਤੀ SSID RSSI ਦਿਖਾਓ"</string>
     <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ਜਦੋਂ ਯੋਗ ਬਣਾਇਆ ਹੋਵੇ, ਤਾਂ ਵਾਈ‑ਫਾਈ ਸਿਗਨਲ ਘੱਟ ਹੋਣ \'ਤੇ ਵਾਈ‑ਫਾਈ ਡਾਟਾ ਕਨੈਕਸ਼ਨ ਮੋਬਾਈਲ ਨੂੰ ਹੈਂਡ ਓਵਰ ਕਰਨ ਵਿੱਚ ਵੱਧ ਆਕਰਮਣਸ਼ੀਲ ਹੋਵੇਗਾ।"</string>
     <string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ਇੰਟਰਫੇਸ ਤੇ ਮੌਜੂਦ ਡਾਟਾ ਟ੍ਰੈਫਿਕ ਦੀ ਮਾਤਰਾ ਦੇ ਆਧਾਰ ਤੇ ਵਾਈ-ਫਾਈ ਰੋਮ ਸਕੈਨ ਦੀ ਆਗਿਆ ਦਿਓ/ਅਸਵੀਕਾਰ ਕਰੋ"</string>
@@ -223,16 +223,16 @@
     <string name="select_usb_configuration_dialog_title" msgid="6385564442851599963">"USB ਕੌਂਫਿਗਰੇਸ਼ਨ ਚੁਣੋ"</string>
     <string name="allow_mock_location" msgid="2787962564578664888">"ਨਕਲੀ ਨਿਰਧਾਰਿਤ ਸਥਾਨਾਂ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
     <string name="allow_mock_location_summary" msgid="317615105156345626">"ਨਕਲੀ ਨਿਰਧਾਰਿਤ ਸਥਾਨਾਂ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
-    <string name="debug_view_attributes" msgid="6485448367803310384">"ਗੁਣ ਛਾਣਬੀਣ ਦੇਖੋ ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
+    <string name="debug_view_attributes" msgid="6485448367803310384">"ਵਿਸ਼ੇਸ਼ਤਾ ਛਾਣਬੀਣ ਦੇਖੋ ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
     <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"ਹਮੇਸ਼ਾਂ ਮੋਬਾਈਲ ਡਾਟਾ ਨੂੰ ਕਿਰਿਆਸ਼ੀਲ ਰੱਖੋ ਭਾਵੇਂ ਵਾਈ‑ਫਾਈ ਕਿਰਿਆਸ਼ੀਲ ਹੋਵੇ (ਤੇਜ਼ ਨੈੱਟਵਰਕ ਸਵਿੱਚਿੰਗ ਲਈ)।"</string>
     <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"ਉਪਲਬਧ ਹੋਣ \'ਤੇ ਟੈਦਰਿੰਗ ਹਾਰਡਵੇਅਰ ਐਕਸੈੱਲਰੇਸ਼ਨ ਵਰਤੋ"</string>
     <string name="adb_warning_title" msgid="6234463310896563253">"ਕੀ USB ਡੀਬਗਿੰਗ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
-    <string name="adb_warning_message" msgid="7316799925425402244">"USB ਡੀਬੱਗਿੰਗ ਕੇਵਲ ਵਿਕਾਸ ਮੰਤਵਾਂ ਲਈ ਹੁੰਦੀ ਹੈ। ਇਸਨੂੰ ਆਪਣੇ ਕੰਪਿਊਟਰ ਅਤੇ ਆਪਣੇ ਡੀਵਾਈਸ ਵਿਚਕਾਰ ਡਾਟਾ ਕਾਪੀ ਕਰਨ ਲਈ ਵਰਤੋ, ਸੂਚਨਾ ਦੇ ਬਿਨਾਂ ਆਪਣੇ ਡੀਵਾਈਸ ਤੇ ਐਪਾਂ ਸਥਾਪਤ ਕਰੋ ਅਤੇ ਲੌਗ ਡਾਟਾ ਪੜ੍ਹੋ।"</string>
+    <string name="adb_warning_message" msgid="7316799925425402244">"USB ਡੀਬਗਿੰਗ ਸਿਰਫ਼ ਵਿਕਾਸ ਮੰਤਵਾਂ ਲਈ ਹੁੰਦੀ ਹੈ। ਇਸਨੂੰ ਆਪਣੇ ਕੰਪਿਊਟਰ ਅਤੇ ਆਪਣੇ ਡੀਵਾਈਸ ਵਿਚਕਾਰ ਡਾਟਾ ਕਾਪੀ ਕਰਨ ਲਈ ਵਰਤੋ, ਸੂਚਨਾ ਦੇ ਬਿਨਾਂ ਆਪਣੇ ਡੀਵਾਈਸ ਤੇ ਐਪਾਂ ਸਥਾਪਤ ਕਰੋ ਅਤੇ ਲੌਗ ਡਾਟਾ ਪੜ੍ਹੋ।"</string>
     <string name="adb_keys_warning_message" msgid="5659849457135841625">"ਕੀ ਉਹਨਾਂ ਸਾਰੇ ਕੰਪਿਊਟਰਾਂ ਤੋਂ USB ਡੀਬੱਗਿੰਗ ਤੱਕ ਪਹੁੰਚ ਰੱਦ ਕਰਨੀ ਹੈ, ਜਿਹਨਾਂ ਲਈ ਪਹਿਲਾਂ ਤੁਸੀਂ ਅਧਿਕਾਰਤ ਕੀਤਾ ਹੈ?"</string>
     <string name="dev_settings_warning_title" msgid="7244607768088540165">"ਕੀ ਵਿਕਾਸ ਸੈਟਿੰਗਾਂ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
     <string name="dev_settings_warning_message" msgid="2298337781139097964">"ਇਹ ਸੈਟਿੰਗਾਂ ਕੇਵਲ ਵਿਕਾਸਕਾਰ ਦੀ ਵਰਤੋਂ ਲਈ ਹਨ। ਇਹ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਅਤੇ ਇਸਤੇ ਮੌਜੂਦ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਬ੍ਰੇਕ ਕਰਨ ਜਾਂ ਦੁਰਵਿਵਹਾਰ ਕਰਨ ਦਾ ਕਾਰਨ ਬਣ ਸਕਦੇ ਹਨ।"</string>
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"USB ਤੇ ਐਪਾਂ ਦੀ ਜਾਂਚ ਕਰੋ"</string>
-    <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ਹਾਨੀਕਾਰਕ ਵਿਵਹਾਰ ਲਈ ADB/ADT ਰਾਹੀਂ ਇੰਸਟੌਲ ਕੀਤੇ ਐਪਸ ਦੀ ਜਾਂਚ ਕਰੋ।"</string>
+    <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ਹਾਨੀਕਾਰਕ ਵਿਵਹਾਰ ਲਈ ADB/ADT ਰਾਹੀਂ ਸਥਾਪਤ ਕੀਤੀਆਂ ਐਪਾਂ ਦੀ ਜਾਂਚ ਕਰੋ।"</string>
     <string name="bluetooth_show_devices_without_names_summary" msgid="2351196058115755520">"ਅਨਾਮ ਬਲੂਟੁੱਥ ਡੀਵਾਈਸਾਂ ਦਿਖਾਈਆਂ ਜਾਣਗੀਆਂ (ਸਿਰਫ਼ MAC ਪਤੇ)"</string>
     <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"ਰਿਮੋਟ ਡੀਵਾਈਸਾਂ ਨਾਲ ਵੌਲਿਊਮ ਸਮੱਸਿਆਵਾਂ ਜਿਵੇਂ ਕਿ ਨਾ ਪਸੰਦ ਕੀਤੀ ਜਾਣ ਵਾਲੀ ਉੱਚੀ ਵੌਲਿਊਮ ਜਾਂ ਕੰਟਰੋਲ ਦੀ ਕਮੀ ਵਰਗੀ ਹਾਲਤ ਵਿੱਚ ਬਲੂਟੁੱਥ ਪੂਰਨ ਵੌਲਿਊਮ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਅਯੋਗ ਬਣਾਉਂਦਾ ਹੈ।"</string>
     <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ਤੁਹਾਡੇ ਫ਼ੋਨ ਦੀਆਂ ਰਿੰਗਟੋਨਾਂ ਨੂੰ ਬਲੂਟੁੱਥ ਹੈੱਡਸੈੱਟਾਂ \'ਤੇ ਚਲਾਉਣ ਦੀ ਇਜਾਜ਼ਤ ਦਿਓ"</string>
@@ -241,13 +241,13 @@
     <string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP ਜਾਂਚ"</string>
     <string name="hdcp_checking_dialog_title" msgid="5141305530923283">"HDCP ਜਾਂਚ ਵਿਵਹਾਰ ਸੈੱਟ ਕਰੋ"</string>
     <string name="debug_debugging_category" msgid="6781250159513471316">"ਡੀਬਗਿੰਗ"</string>
-    <string name="debug_app" msgid="8349591734751384446">"ਡੀਬਗ ਐਪ ਚੁਣੋ"</string>
-    <string name="debug_app_not_set" msgid="718752499586403499">"ਕੋਈ ਡੀਬਗ ਐਪਲੀਕੇਸ਼ਨ ਸੈਟ ਨਹੀਂ ਕੀਤੀ"</string>
+    <string name="debug_app" msgid="8349591734751384446">"ਡੀਬੱਗ ਐਪ ਚੁਣੋ"</string>
+    <string name="debug_app_not_set" msgid="718752499586403499">"ਕੋਈ ਡੀਬੱਗ ਐਪਲੀਕੇਸ਼ਨ ਸੈੱਟ ਨਹੀਂ ਕੀਤੀ"</string>
     <string name="debug_app_set" msgid="2063077997870280017">"ਡੀਬਗਿੰਗ ਐਪਲੀਕੇਸ਼ਨ: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="select_application" msgid="5156029161289091703">"ਐਪਲੀਕੇਸ਼ਨ ਚੁਣੋ"</string>
     <string name="no_application" msgid="2813387563129153880">"ਕੁਝ ਨਹੀਂ"</string>
-    <string name="wait_for_debugger" msgid="1202370874528893091">"ਡੀਬਗਰ ਦੀ ਉਡੀਕ ਕਰੋ"</string>
-    <string name="wait_for_debugger_summary" msgid="1766918303462746804">"ਡੀਬਗ ਕੀਤੇ ਐਪਲੀਕੇਸ਼ਨ ਐਗਜੀਕਿਊਟ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਅਟੈਚ ਕਰਨ ਲਈ ਡੀਬਗਰ ਦੀ ਉਡੀਕ ਕਰਦੇ ਹਨ"</string>
+    <string name="wait_for_debugger" msgid="1202370874528893091">"ਡੀਬੱਗਰ ਦੀ ਉਡੀਕ ਕਰੋ"</string>
+    <string name="wait_for_debugger_summary" msgid="1766918303462746804">"ਡੀਬੱਗ ਕੀਤੇ ਐਪਲੀਕੇਸ਼ਨ ਐਗਜੀਕਿਊਟ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਅਟੈਚ ਕਰਨ ਲਈ ਡੀਬੱਗਰ ਦੀ ਉਡੀਕ ਕਰਦੇ ਹਨ"</string>
     <string name="telephony_monitor_switch" msgid="1764958220062121194">"ਟੈਲੀਫ਼ੋਨੀ ਮੋਨੀਟਰ"</string>
     <string name="telephony_monitor_switch_summary" msgid="7695552966547975635">"ਟੈਲੀਫ਼ੋਨੀ ਮੋਨੀਟਰ ਟੈਲੀਫ਼ੋਨੀ/ਮੌਡਮ ਪ੍ਰਕਾਰਜਾਤਮਕਤਾ ਵਿੱਚ ਕਿਸੇ ਸਮੱਸਿਆ ਦਾ ਪਤਾ ਲੱਗਣ \'ਤੇ ਲੌਗਾਂ ਨੂੰ ਇਕੱਤਰ ਕਰੇਗਾ ਅਤੇ ਵਰਤੋਂਕਾਰ ਨੂੰ ਇੱਕ ਬੱਗ ਦਾਇਰ ਕਰਨ ਲਈ ਸੂਚਨਾ ਦੇਵੇਗਾ"</string>
     <string name="debug_input_category" msgid="1811069939601180246">"ਇਨਪੁਟ"</string>
@@ -262,11 +262,11 @@
     <string name="show_touches" msgid="2642976305235070316">"ਟੈਪਾਂ  ਦਿਖਾਓ"</string>
     <string name="show_touches_summary" msgid="6101183132903926324">"ਟੈਪਾਂ ਲਈ ਨਜ਼ਰ ਸਬੰਧੀ ਪ੍ਰਤੀਕਰਮ  ਦਿਖਾਓ"</string>
     <string name="show_screen_updates" msgid="5470814345876056420">"ਸਰਫਸ ਅਪਡੇਟਾਂ ਦਿਖਾਓ"</string>
-    <string name="show_screen_updates_summary" msgid="2569622766672785529">"ਸਮੁੱਚੀ ਵਿੰਡੋ ਸਰਫੇਸਾਂ ਫਲੈਸ਼ ਕਰੋ ਜਦੋਂ ਉਹ ਅੱਪਡੇਟ ਹੁੰਦੀਆਂ ਹਨ"</string>
+    <string name="show_screen_updates_summary" msgid="2569622766672785529">"ਵਿੰਡੋ ਦੇ ਸਮੁੱਚੇ ਤਲਾਂ ਦੇ ਅੱਪਡੇਟ ਹੋਣ \'ਤੇ ਉਨ੍ਹਾਂ ਨੂੰ ਰੌਸ਼ਨ ਕਰੋ"</string>
     <string name="show_hw_screen_updates" msgid="5036904558145941590">"GPU ਦ੍ਰਿਸ਼ ਅੱਪਡੇਟਾਂ ਦਿਖਾਓ"</string>
     <string name="show_hw_screen_updates_summary" msgid="1115593565980196197">"ਜਦੋਂ GPU ਨਾਲ ਡ੍ਰਾ ਕੀਤਾ ਜਾਏ ਤਾਂ ਵਿੰਡੋਜ਼ ਦੇ ਅੰਦਰ ਦ੍ਰਿਸ਼ ਫਲੈਸ਼ ਕਰੋ"</string>
     <string name="show_hw_layers_updates" msgid="5645728765605699821">"ਹਾਰਡਵੇਅਰ ਲੇਅਰਾਂ ਦੇ ਅੱਪਡੇਟਾਂ ਦਿਖਾਓ"</string>
-    <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ਹਾਰਡਵੇਅਰ ਲੇਅਰਾਂ ਹਰੀਆਂ ਫਲੈਸ਼ ਕਰੋ ਜਦੋਂ ਉਹ ਅੱਪਡੇਟ ਹੁੰਦੀਆਂ ਹਨ"</string>
+    <string name="show_hw_layers_updates_summary" msgid="5296917233236661465">"ਹਾਰਡਵੇਅਰ ਲੇਅਰਾਂ ਅੱਪਡੇਟ ਹੋਣ \'ਤੇ ਉਨ੍ਹਾਂ ਨੂੰ ਹਰਾ ਕਰੋ"</string>
     <string name="debug_hw_overdraw" msgid="2968692419951565417">"GPU ਓਵਰਡ੍ਰਾ ਡੀਬੱਗ ਕਰੋ"</string>
     <string name="debug_hw_renderer" msgid="7568529019431785816">"GPU ਰੈਂਡਰਰ ਸੈੱਟ ਕਰੋ"</string>
     <string name="disable_overlays" msgid="2074488440505934665">"HW ਓਵਰਲੇਜ ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਓ"</string>
@@ -283,7 +283,7 @@
     <string name="force_hw_ui_summary" msgid="5535991166074861515">"2d ਡ੍ਰਾਇੰਗ ਲਈ GPU ਦੀ ਵਰਤੋਂ ਤੇ ਜ਼ੋਰ ਪਾਓ"</string>
     <string name="force_msaa" msgid="7920323238677284387">"4x MSAA ਤੇ ਜ਼ੋਰ ਪਾਓ"</string>
     <string name="force_msaa_summary" msgid="9123553203895817537">"OpenGL ES 2.0 ਐਪਾਂ ਵਿੱਚ 4x MSAA ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
-    <string name="show_non_rect_clip" msgid="505954950474595172">"ਗ਼ੈਰ-ਆਇਤਾਕਾਰ ਕਲਿਪ ਓਪਰੇਸ਼ਨ ਡੀਬਗ ਕਰੋ"</string>
+    <string name="show_non_rect_clip" msgid="505954950474595172">"ਗੈਰ-ਆਇਤਾਕਾਰ ਕਲਿੱਪ ਓਪਰੇਸ਼ਨ ਡੀਬੱਗ ਕਰੋ"</string>
     <string name="track_frame_time" msgid="6146354853663863443">"ਪ੍ਰੋਫਾਈਲ GPU ਰੈਂਡਰਿੰਗ"</string>
     <string name="window_animation_scale_title" msgid="6162587588166114700">"ਵਿੰਡੋ ਐਨੀਮੇਸ਼ਨ ਸਕੇਲ"</string>
     <string name="transition_animation_scale_title" msgid="387527540523595875">"ਟ੍ਰਾਂਜਿਸ਼ਨ ਐਨੀਮੇਸ਼ਨ ਸਕੇਲ"</string>
@@ -304,7 +304,7 @@
     <string name="enable_freeform_support" msgid="1461893351278940416">"freeform windows ਨੂੰ ਚਾਲੂ ਕਰੋ"</string>
     <string name="enable_freeform_support_summary" msgid="8247310463288834487">"ਪ੍ਰਯੋਗਮਈ ਫ੍ਰੀਫਾਰਮ ਵਿੰਡੋਜ਼ ਲਈ ਸਮਰਥਨ ਨੂੰ ਚਾਲੂ ਕਰੋ।"</string>
     <string name="local_backup_password_title" msgid="3860471654439418822">"ਡੈਸਕਟਾਪ ਬੈਕਅੱਪ ਪਾਸਵਰਡ"</string>
-    <string name="local_backup_password_summary_none" msgid="6951095485537767956">"ਡੈਸਕਟੌਪ ਪੂਰੇ ਬੈਕਅਪਸ ਇਸ ਵੇਲੇ ਸੁਰੱਖਿਅਤ ਨਹੀਂ ਹਨ"</string>
+    <string name="local_backup_password_summary_none" msgid="6951095485537767956">"ਡੈਸਕਟਾਪ ਪੂਰੇ ਬੈਕਅੱਪ ਇਸ ਵੇਲੇ ਸੁਰੱਖਿਅਤ ਨਹੀਂ ਹਨ"</string>
     <string name="local_backup_password_summary_change" msgid="5376206246809190364">"ਡੈਸਕਟਾਪ ਦੇ ਮੁਕੰਮਲ ਬੈਕਅੱਪਾਂ ਲਈ ਪਾਸਵਰਡ ਨੂੰ ਬਦਲਣ ਜਾਂ ਹਟਾਉਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="local_backup_password_toast_success" msgid="582016086228434290">"ਨਵਾਂ ਬੈਕਅੱਪ ਪਾਸਵਰਡ ਸੈੱਟ ਕੀਤਾ ਗਿਆ"</string>
     <string name="local_backup_password_toast_confirmation_mismatch" msgid="7805892532752708288">"ਨਵਾਂ ਪਾਸਵਰਡ ਅਤੇ ਪੁਸ਼ਟੀ ਮੇਲ ਨਹੀਂ ਖਾਂਦੀ"</string>
@@ -365,7 +365,7 @@
     <string name="disabled" msgid="9206776641295849915">"ਅਯੋਗ ਬਣਾਇਆ"</string>
     <string name="external_source_trusted" msgid="2707996266575928037">"ਇਜਾਜ਼ਤ ਹੈ"</string>
     <string name="external_source_untrusted" msgid="2677442511837596726">"ਇਜਾਜ਼ਤ ਨਹੀਂ"</string>
-    <string name="install_other_apps" msgid="6986686991775883017">"ਅਗਿਆਤ ਐਪਾਂ ਸਥਾਪਿਤ ਕਰੋ"</string>
+    <string name="install_other_apps" msgid="6986686991775883017">"ਅਗਿਆਤ ਐਪਾਂ ਸਥਾਪਤ ਕਰੋ"</string>
     <string name="home" msgid="3256884684164448244">"ਸੈਟਿੰਗਾਂ ਮੁੱਖ ਪੰਨਾ"</string>
   <string-array name="battery_labels">
     <item msgid="8494684293649631252">"0%"</item>
@@ -379,7 +379,7 @@
     <string name="screen_zoom_summary_large" msgid="4835294730065424084">"ਵੱਡੀ"</string>
     <string name="screen_zoom_summary_very_large" msgid="7108563375663670067">"ਥੋੜ੍ਹਾ ਵੱਡੀ"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="7427320168263276227">"ਸਭ ਤੋਂ ਵੱਡੀ"</string>
-    <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+    <string name="screen_zoom_summary_custom" msgid="5611979864124160447">"ਵਿਉਂਂਤੀ (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="help_feedback_label" msgid="6815040660801785649">"ਮਦਦ &amp; ਫੀਡਬੈਕ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"ਮੀਨੂ"</string>
     <string name="retail_demo_reset_message" msgid="118771671364131297">"ਡੈਮੋ ਮੋਡ \'ਚ ਫੈਕਟਰੀ ਰੀਸੈੱਟ ਲਈ ਪਾਸਵਰਡ ਦਿਓ"</string>
@@ -389,5 +389,5 @@
     <string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"ਸਿਸਟਮ ਭਾਸ਼ਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
     <string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"<xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> ਲਈ ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹਣ ਵਿੱਚ ਅਸਫਲ"</string>
     <string name="ime_security_warning" msgid="4135828934735934248">"ਇਹ ਇਨਪੁੱਟ ਵਿਧੀ ਤੁਹਾਡੇ ਵੱਲੋਂ ਟਾਈਪ ਕੀਤਾ ਜਾਣ ਵਾਲੀ ਸਾਰੀ ਲਿਖਤ ਇਕੱਤਰ ਕਰਨ ਵਿੱਚ ਸਮਰੱਥ ਹੋ ਸਕਦੀ ਹੈ, ਨਿੱਜੀ ਡਾਟਾ ਸਮੇਤ ਜਿਵੇਂ ਪਾਸਵਰਡ ਅਤੇ ਕ੍ਰੈਡਿਟ ਕਾਰਡ ਨੰਬਰ। ਇਹ <xliff:g id="IME_APPLICATION_NAME">%1$s</xliff:g> ਐਪ ਤੋਂ ਆਉਂਦਾ ਹੈ। ਕੀ ਇਹ ਸਪੈੱਲ ਚੈਕਰ ਵਰਤਣਾ ਹੈ?"</string>
-    <string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"ਨੋਟ ਕਰੋ: ਰੀਬੂਟ ਤੋਂ ਬਾਅਦ, ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਆਪਣਾ ਫ਼ੋਨ ਅਨਲੌਕ ਨਹੀਂ ਕਰਦੇ ਤਦ ਤੱਕ ਇਹ ਐਪ ਚਾਲੂ ਨਹੀਂ ਹੋ ਸਕਦੀ"</string>
+    <string name="direct_boot_unaware_dialog_message" msgid="7870273558547549125">"ਨੋਟ ਕਰੋ: ਰੀਬੂਟ ਤੋਂ ਬਾਅਦ, ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਆਪਣਾ ਫ਼ੋਨ ਅਣਲਾਕ ਨਹੀਂ ਕਰਦੇ ਤਦ ਤੱਕ ਇਹ ਐਪ ਚਾਲੂ ਨਹੀਂ ਹੋ ਸਕਦੀ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml
index b47a7e7..c0427c8 100644
--- a/packages/SettingsLib/res/values-pl/arrays.xml
+++ b/packages/SettingsLib/res/values-pl/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Użyj sprawdzania HDCP tylko w przypadku treści chronionych DRM"</item>
     <item msgid="45075631231212732">"Zawsze używaj sprawdzania HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (domyślna)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Użyj wyboru systemu (domyślnie)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
index eb7d967..4695829 100644
--- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Usar a verificação HDCP somente para conteúdo DRM"</item>
     <item msgid="45075631231212732">"Sempre usar a verificação HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (padrão)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Usar seleção do sistema (padrão)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-pt-rPT/arrays.xml b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
index 4774391..78a24c4 100644
--- a/packages/SettingsLib/res/values-pt-rPT/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Utilizar a verificação HDCP para conteúdo DRM apenas"</item>
     <item msgid="45075631231212732">"Utilizar sempre a verificação HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (predefinição)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Utilizar seleção do sistema (predef.)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml
index eb7d967..4695829 100644
--- a/packages/SettingsLib/res/values-pt/arrays.xml
+++ b/packages/SettingsLib/res/values-pt/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Usar a verificação HDCP somente para conteúdo DRM"</item>
     <item msgid="45075631231212732">"Sempre usar a verificação HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (padrão)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Usar seleção do sistema (padrão)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index ccd7718..b62014e 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Utilizează verificarea HDCP numai pentru conținut DRM"</item>
     <item msgid="45075631231212732">"Utilizează întotdeauna verificarea HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (prestabilit)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Folosiți selectarea sist. (prestabilit)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ru/arrays.xml b/packages/SettingsLib/res/values-ru/arrays.xml
index 6f47484..05ccc80 100644
--- a/packages/SettingsLib/res/values-ru/arrays.xml
+++ b/packages/SettingsLib/res/values-ru/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Использовать проверку HDCP только для DRM-контента"</item>
     <item msgid="45075631231212732">"Всегда использовать проверку HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (по умолчанию)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Выбор системы (по умолчанию)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-si/arrays.xml b/packages/SettingsLib/res/values-si/arrays.xml
index 19bd549..2808ba3 100644
--- a/packages/SettingsLib/res/values-si/arrays.xml
+++ b/packages/SettingsLib/res/values-si/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"DRM අන්තර්ගත සඳහා පමණක් HDCP පරික්ෂාව භාවිතා කරන්න"</item>
     <item msgid="45075631231212732">"සැමවිටම HDCP පිරික්සුම භාවිතා කරන්න"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (පෙරනිමි)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"පද්ධති තේරීම භාවිත කරන්න (පෙරනිමි)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml
index ab94876..f3c25b4 100644
--- a/packages/SettingsLib/res/values-sk/arrays.xml
+++ b/packages/SettingsLib/res/values-sk/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Použiť kontrolu HDCP len pre obsah DRM"</item>
     <item msgid="45075631231212732">"Vždy používať kontrolu HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (predvolené)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Použiť voľbu systému (predvolené)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-sl/arrays.xml b/packages/SettingsLib/res/values-sl/arrays.xml
index c291624..a924bdb 100644
--- a/packages/SettingsLib/res/values-sl/arrays.xml
+++ b/packages/SettingsLib/res/values-sl/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Preverjanje HDCP uporabi samo za vsebino DRM"</item>
     <item msgid="45075631231212732">"Vedno uporabi preverjanje HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (privzeto)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Uporabi sistemsko izbiro (privzeto)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-sq/arrays.xml b/packages/SettingsLib/res/values-sq/arrays.xml
index 64fdc63..244a534 100644
--- a/packages/SettingsLib/res/values-sq/arrays.xml
+++ b/packages/SettingsLib/res/values-sq/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Përdor kontrollin e HDCP-së vetëm për përmbajtjet DRM"</item>
     <item msgid="45075631231212732">"Përdor gjithmonë kontrollin e HDCP-së"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (I parazgjedhur)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-sr/arrays.xml b/packages/SettingsLib/res/values-sr/arrays.xml
index 02ed636..4486bf1 100644
--- a/packages/SettingsLib/res/values-sr/arrays.xml
+++ b/packages/SettingsLib/res/values-sr/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Користи HDCP проверу само за DRM садржај"</item>
     <item msgid="45075631231212732">"Увек користи HDCP проверу"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (подразумевано)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Користи избор система (подразумевано)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-sv/arrays.xml b/packages/SettingsLib/res/values-sv/arrays.xml
index 51f8c19..cc7bcc8 100644
--- a/packages/SettingsLib/res/values-sv/arrays.xml
+++ b/packages/SettingsLib/res/values-sv/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Använd bara HDCP-kontroll för DRM-innehåll"</item>
     <item msgid="45075631231212732">"Använd alltid HDCP-kontroll"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (standard)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Använd systemval (standardinställning)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
@@ -167,31 +173,31 @@
     <item msgid="8489661142527693381">"endast buffert av kernellogg"</item>
   </string-array>
   <string-array name="window_animation_scale_entries">
-    <item msgid="8134156599370824081">"Animering avstängd"</item>
-    <item msgid="6624864048416710414">"Animering i skala 0,5x"</item>
-    <item msgid="2219332261255416635">"Animering i skala 1x"</item>
-    <item msgid="3544428804137048509">"Animering i skala 1,5x"</item>
-    <item msgid="3110710404225974514">"Animering i skala 2x"</item>
-    <item msgid="4402738611528318731">"Animering i skala 5x"</item>
-    <item msgid="6189539267968330656">"Animering i skala 10x"</item>
+    <item msgid="8134156599370824081">"Animation avstängd"</item>
+    <item msgid="6624864048416710414">"Animation i skala 0,5x"</item>
+    <item msgid="2219332261255416635">"Animation i skala 1x"</item>
+    <item msgid="3544428804137048509">"Animation i skala 1,5x"</item>
+    <item msgid="3110710404225974514">"Animation i skala 2x"</item>
+    <item msgid="4402738611528318731">"Animation i skala 5x"</item>
+    <item msgid="6189539267968330656">"Animation i skala 10x"</item>
   </string-array>
   <string-array name="transition_animation_scale_entries">
-    <item msgid="8464255836173039442">"Animering avstängd"</item>
-    <item msgid="3375781541913316411">"Animering i skala 0,5x"</item>
-    <item msgid="1991041427801869945">"Animering i skala 1x"</item>
-    <item msgid="4012689927622382874">"Animering i skala 1,5x"</item>
-    <item msgid="3289156759925947169">"Animering i skala 2x"</item>
-    <item msgid="7705857441213621835">"Animering i skala 5x"</item>
-    <item msgid="6660750935954853365">"Animering i skala 10x"</item>
+    <item msgid="8464255836173039442">"Animation avstängd"</item>
+    <item msgid="3375781541913316411">"Animation i skala 0,5x"</item>
+    <item msgid="1991041427801869945">"Animation i skala 1x"</item>
+    <item msgid="4012689927622382874">"Animation i skala 1,5x"</item>
+    <item msgid="3289156759925947169">"Animation i skala 2x"</item>
+    <item msgid="7705857441213621835">"Animation i skala 5x"</item>
+    <item msgid="6660750935954853365">"Animation i skala 10x"</item>
   </string-array>
   <string-array name="animator_duration_scale_entries">
-    <item msgid="6039901060648228241">"Animering avstängd"</item>
-    <item msgid="1138649021950863198">"Animering i skala 0,5x"</item>
-    <item msgid="4394388961370833040">"Animering i skala 1x"</item>
-    <item msgid="8125427921655194973">"Animering i skala 1,5x"</item>
-    <item msgid="3334024790739189573">"Animering i skala 2x"</item>
-    <item msgid="3170120558236848008">"Animering i skala 5x"</item>
-    <item msgid="1069584980746680398">"Animering i skala 10x"</item>
+    <item msgid="6039901060648228241">"Animation avstängd"</item>
+    <item msgid="1138649021950863198">"Animation i skala 0,5x"</item>
+    <item msgid="4394388961370833040">"Animation i skala 1x"</item>
+    <item msgid="8125427921655194973">"Animation i skala 1,5x"</item>
+    <item msgid="3334024790739189573">"Animation i skala 2x"</item>
+    <item msgid="3170120558236848008">"Animation i skala 5x"</item>
+    <item msgid="1069584980746680398">"Animation i skala 10x"</item>
   </string-array>
   <string-array name="overlay_display_devices_entries">
     <item msgid="1606809880904982133">"Inga"</item>
diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml
index fdc1baf..b694687 100644
--- a/packages/SettingsLib/res/values-sw/arrays.xml
+++ b/packages/SettingsLib/res/values-sw/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Tumia ukaguaji wa HDCP kwa maudhui ya DRM pekee"</item>
     <item msgid="45075631231212732">"Kila wakati tumia ukakuaji wa HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (Chaguo-msingi)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Tumia Uteuzi wa Mfumo (Chaguo-msingi)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ta/arrays.xml b/packages/SettingsLib/res/values-ta/arrays.xml
index 62d66f5..2d75c01 100644
--- a/packages/SettingsLib/res/values-ta/arrays.xml
+++ b/packages/SettingsLib/res/values-ta/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"DRM உள்ளடக்கத்திற்கு மட்டும் HDCP சோதனையைப் பயன்படுத்து"</item>
     <item msgid="45075631231212732">"HDCP சரிபார்ப்பை எப்போதும் பயன்படுத்து"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (இயல்பு)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"சாதனத் தேர்வைப் பயன்படுத்து (இயல்பு)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index 5915fb7..39d84dd 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"DRM కంటెంట్‌కు మాత్రమే HDCP తనిఖీని ఉపయోగించండి"</item>
     <item msgid="45075631231212732">"ఎప్పటికీ HDCP తనిఖీని ఉపయోగించు"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (డిఫాల్ట్)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"సిస్టమ్ ఎంపికను ఉపయోగించండి (డిఫాల్ట్)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml
index 3d3d8f4..6d1c5d7 100644
--- a/packages/SettingsLib/res/values-th/arrays.xml
+++ b/packages/SettingsLib/res/values-th/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"ใช้การตรวจสอบ HDCP สำหรับเนื้อหา DRM เท่านั้น"</item>
     <item msgid="45075631231212732">"ใช้การตรวจสอบ HDCP เสมอ"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (ค่าเริ่มต้น)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"ใช้การเลือกระบบ (ค่าเริ่มต้น)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-tl/arrays.xml b/packages/SettingsLib/res/values-tl/arrays.xml
index 886da95..7a3fd30 100644
--- a/packages/SettingsLib/res/values-tl/arrays.xml
+++ b/packages/SettingsLib/res/values-tl/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Gamitin lang ang pagsusuring HDCP para sa nilalamang DRM"</item>
     <item msgid="45075631231212732">"Palaging gumamit ng pagsusuring HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (Default)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Gamitin ang Pagpili ng System (Default)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-tr/arrays.xml b/packages/SettingsLib/res/values-tr/arrays.xml
index 8c410dc..2a70fda 100644
--- a/packages/SettingsLib/res/values-tr/arrays.xml
+++ b/packages/SettingsLib/res/values-tr/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"HDCP denetimini yalnızca DRM içeriği için kullan"</item>
     <item msgid="45075631231212732">"HDCP denetimini her zaman kullan"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (Varsayılan)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Sistem Seçimini Kullan (Varsayılan)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-uk/arrays.xml b/packages/SettingsLib/res/values-uk/arrays.xml
index 4ed308c..e3f21ad 100644
--- a/packages/SettingsLib/res/values-uk/arrays.xml
+++ b/packages/SettingsLib/res/values-uk/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Використовувати перевірку HDCP лише для вмісту, захищеного DRM"</item>
     <item msgid="45075631231212732">"Завжди використовувати перевірку HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (за умовчанням)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"acrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Використовувати вибір системи (за умовчанням)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml
index 8b4ae40..8d46582 100644
--- a/packages/SettingsLib/res/values-ur/arrays.xml
+++ b/packages/SettingsLib/res/values-ur/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"‏HDCP چیکنگ صرف DRM مواد کیلئے استعمال کریں"</item>
     <item msgid="45075631231212732">"‏ہمیشہ HDCP چیکنگ استعمال کریں"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"‏AVRCP 1.4 (ڈیفالٹ)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml
index 4fa26c2..16d325fe 100644
--- a/packages/SettingsLib/res/values-uz/arrays.xml
+++ b/packages/SettingsLib/res/values-uz/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"HDCP tekshiruvi faqat DRM kontent uchun ishlatilsin"</item>
     <item msgid="45075631231212732">"Har doim HDCP tekshiruvidan foydalanilsin"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (asosiy)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Tizim tanlovi (birlamchi)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-vi/arrays.xml b/packages/SettingsLib/res/values-vi/arrays.xml
index c9f3c33..57e749f 100644
--- a/packages/SettingsLib/res/values-vi/arrays.xml
+++ b/packages/SettingsLib/res/values-vi/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Chỉ sử dụng kiểm tra HDCP cho nội dung DRM"</item>
     <item msgid="45075631231212732">"Luôn sử dụng kiểm tra HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (Mặc định)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Sử dụng lựa chọn hệ thống (Mặc định)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
index 655bb62..3a80e7b 100644
--- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"仅使用 HDCP 检查 DRM 内容"</item>
     <item msgid="45075631231212732">"始终使用 HDCP 检查"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4(默认)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"使用系统选择(默认)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-zh-rHK/arrays.xml b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
index 7432ab4..85c151e 100644
--- a/packages/SettingsLib/res/values-zh-rHK/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"僅使用 HDCP 檢查 DRM 內容"</item>
     <item msgid="45075631231212732">"永遠使用 HDCP 檢查"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (預設)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"使用系統選擇 (預設)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
index f5f3424..ce2e89fd 100644
--- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"僅使用 HDCP 檢查 DRM 內容"</item>
     <item msgid="45075631231212732">"一律使用 HDCP 檢查"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"AVRCP 1.4 (預設)"</item>
+    <item msgid="2809759619990248160">"AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"avrcp14"</item>
+    <item msgid="3011533352527449572">"avrcp13"</item>
+    <item msgid="8837606198371920819">"avrcp15"</item>
+    <item msgid="3422726142222090896">"avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"使用系統選擇 (預設)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values-zu/arrays.xml b/packages/SettingsLib/res/values-zu/arrays.xml
index 7ec4745..3d0de36 100644
--- a/packages/SettingsLib/res/values-zu/arrays.xml
+++ b/packages/SettingsLib/res/values-zu/arrays.xml
@@ -58,12 +58,18 @@
     <item msgid="3878793616631049349">"Sebenzisa ukuhlola kwe-HDCP kokuqukethwe i-DRM kuphela"</item>
     <item msgid="45075631231212732">"Sebenzisa njalo ukuhlola kwe-HDPC"</item>
   </string-array>
-    <!-- no translation found for bluetooth_avrcp_versions:1 (2809759619990248160) -->
-    <!-- no translation found for bluetooth_avrcp_versions:2 (6199178154704729352) -->
-    <!-- no translation found for bluetooth_avrcp_versions:3 (5172170854953034852) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:1 (3011533352527449572) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:2 (8837606198371920819) -->
-    <!-- no translation found for bluetooth_avrcp_version_values:3 (3422726142222090896) -->
+  <string-array name="bluetooth_avrcp_versions">
+    <item msgid="5347678900838034763">"I-AVRCP 1.4 (Okuzenzakalelayo)"</item>
+    <item msgid="2809759619990248160">"I-AVRCP 1.3"</item>
+    <item msgid="6199178154704729352">"I-AVRCP 1.5"</item>
+    <item msgid="5172170854953034852">"I-AVRCP 1.6"</item>
+  </string-array>
+  <string-array name="bluetooth_avrcp_version_values">
+    <item msgid="2838624067805073303">"I-avrcp14"</item>
+    <item msgid="3011533352527449572">"I-avrcp13"</item>
+    <item msgid="8837606198371920819">"I-avrcp15"</item>
+    <item msgid="3422726142222090896">"I-avrcp16"</item>
+  </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
     <item msgid="7065842274271279580">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index 1e35cbc..e261570 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -61,10 +61,13 @@
     <fraction name="battery_button_height_fraction">10.5%</fraction>
 
     <!-- Ratio between height of button part and height of total -->
-    <fraction name="bt_battery_button_height_fraction">7.5%</fraction>
+    <fraction name="bt_battery_button_height_fraction">7.8%</fraction>
 
     <!-- Ratio between width and height -->
-    <fraction name="bt_battery_ratio_fraction">45%</fraction>
+    <fraction name="bt_battery_ratio_fraction">35%</fraction>
+
+    <!-- Ratio of height between battery icon and bluetooth icon -->
+    <fraction name="bt_battery_scale_fraction">75%</fraction>
 
     <!-- Fraction value to smooth the edges of the battery icon. The path will be inset by this
          fraction of a pixel.-->
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index bf1bf34..40c2b1f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -339,26 +339,35 @@
         synchronized (mEntriesMap) {
             AppEntry entry = mEntriesMap.get(userId).get(packageName);
             if (entry != null && (entry.info.flags & ApplicationInfo.FLAG_INSTALLED) != 0) {
-                mBackgroundHandler.post(() -> {
-                    try {
-                        final StorageStats stats = mStats.queryStatsForPackage(
-                                entry.info.storageUuid, packageName, UserHandle.of(userId));
-                        final PackageStats legacy = new PackageStats(packageName, userId);
-                        legacy.codeSize = stats.getCodeBytes();
-                        legacy.dataSize = stats.getDataBytes();
-                        legacy.cacheSize = stats.getCacheBytes();
-                        try {
-                            mBackgroundHandler.mStatsObserver.onGetStatsCompleted(legacy, true);
-                        } catch (RemoteException ignored) {
-                        }
-                    } catch (NameNotFoundException | IOException e) {
-                        Log.w(TAG, "Failed to query stats: " + e);
-                        try {
-                            mBackgroundHandler.mStatsObserver.onGetStatsCompleted(null, false);
-                        } catch (RemoteException ignored) {
-                        }
-                    }
-                });
+                mBackgroundHandler.post(
+                        () -> {
+                            try {
+                                final StorageStats stats =
+                                        mStats.queryStatsForPackage(
+                                                entry.info.storageUuid,
+                                                packageName,
+                                                UserHandle.of(userId));
+                                final long cacheQuota =
+                                        mStats.getCacheQuotaBytes(
+                                                entry.info.storageUuid.toString(), entry.info.uid);
+                                final PackageStats legacy = new PackageStats(packageName, userId);
+                                legacy.codeSize = stats.getCodeBytes();
+                                legacy.dataSize = stats.getDataBytes();
+                                legacy.cacheSize = Math.min(stats.getCacheBytes(), cacheQuota);
+                                try {
+                                    mBackgroundHandler.mStatsObserver.onGetStatsCompleted(
+                                            legacy, true);
+                                } catch (RemoteException ignored) {
+                                }
+                            } catch (NameNotFoundException | IOException e) {
+                                Log.w(TAG, "Failed to query stats: " + e);
+                                try {
+                                    mBackgroundHandler.mStatsObserver.onGetStatsCompleted(
+                                            null, false);
+                                } catch (RemoteException ignored) {
+                                }
+                            }
+                        });
             }
             if (DEBUG_LOCKING) Log.v(TAG, "...requestSize releasing lock");
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index 9620a91..6e676bc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -326,6 +326,15 @@
             Context context, UserHandle user, Intent intent,
             Map<Pair<String, String>, Tile> addedCache, String defaultCategory, List<Tile> outTiles,
             boolean usePriority, boolean checkCategory, boolean forceTintExternalIcon) {
+        getTilesForIntent(context, user, intent, addedCache, defaultCategory, outTiles,
+                usePriority, checkCategory, forceTintExternalIcon, false /* shouldUpdateTiles */);
+    }
+
+    public static void getTilesForIntent(
+            Context context, UserHandle user, Intent intent,
+            Map<Pair<String, String>, Tile> addedCache, String defaultCategory, List<Tile> outTiles,
+            boolean usePriority, boolean checkCategory, boolean forceTintExternalIcon,
+            boolean shouldUpdateTiles) {
         PackageManager pm = context.getPackageManager();
         List<ResolveInfo> results = pm.queryIntentActivitiesAsUser(intent,
                 PackageManager.GET_META_DATA, user.getIdentifier());
@@ -363,9 +372,11 @@
                 updateTileData(context, tile, activityInfo, activityInfo.applicationInfo,
                         pm, providerMap, forceTintExternalIcon);
                 if (DEBUG) Log.d(LOG_TAG, "Adding tile " + tile.title);
-
                 addedCache.put(key, tile);
+            } else if (shouldUpdateTiles) {
+                updateSummaryAndTitle(context, providerMap, tile);
             }
+
             if (!tile.userHandle.contains(user)) {
                 tile.userHandle.add(user);
             }
@@ -386,7 +397,6 @@
             String summary = null;
             String keyHint = null;
             boolean isIconTintable = false;
-            RemoteViews remoteViews = null;
 
             // Get the activity's meta-data
             try {
@@ -441,16 +451,8 @@
                     }
                     if (metaData.containsKey(META_DATA_PREFERENCE_CUSTOM_VIEW)) {
                         int layoutId = metaData.getInt(META_DATA_PREFERENCE_CUSTOM_VIEW);
-                        remoteViews = new RemoteViews(applicationInfo.packageName, layoutId);
-                        if (metaData.containsKey(META_DATA_PREFERENCE_SUMMARY_URI)) {
-                            String uriString = metaData.getString(
-                                    META_DATA_PREFERENCE_SUMMARY_URI);
-                            String overrideSummary = getTextFromUri(context, uriString, providerMap,
-                                    META_DATA_PREFERENCE_SUMMARY);
-                            if (overrideSummary != null) {
-                                remoteViews.setTextViewText(android.R.id.summary, overrideSummary);
-                            }
-                        }
+                        tile.remoteViews = new RemoteViews(applicationInfo.packageName, layoutId);
+                        updateSummaryAndTitle(context, providerMap, tile);
                     }
                 }
             } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
@@ -482,7 +484,6 @@
             // Suggest a key for this tile
             tile.key = keyHint;
             tile.isIconTintable = isIconTintable;
-            tile.remoteViews = remoteViews;
 
             return true;
         }
@@ -490,6 +491,26 @@
         return false;
     }
 
+    private static void updateSummaryAndTitle(
+            Context context, Map<String, IContentProvider> providerMap, Tile tile) {
+        if (tile == null || tile.metaData == null
+                || !tile.metaData.containsKey(META_DATA_PREFERENCE_SUMMARY_URI)) {
+            return;
+        }
+
+        String uriString = tile.metaData.getString(META_DATA_PREFERENCE_SUMMARY_URI);
+        Bundle bundle = getBundleFromUri(context, uriString, providerMap);
+        String overrideSummary = getString(bundle, META_DATA_PREFERENCE_SUMMARY);
+        String overrideTitle = getString(bundle, META_DATA_PREFERENCE_TITLE);
+        if (overrideSummary != null) {
+            tile.remoteViews.setTextViewText(android.R.id.summary, overrideSummary);
+        }
+
+        if (overrideTitle != null) {
+            tile.remoteViews.setTextViewText(android.R.id.title, overrideTitle);
+        }
+    }
+
     /**
      * Gets the icon package name and resource id from content provider.
      * @param Context context
@@ -555,6 +576,10 @@
         }
     }
 
+    private static String getString(Bundle bundle, String key) {
+        return bundle == null ? null : bundle.getString(key);
+    }
+
     private static IContentProvider getProviderFromUri(Context context, Uri uri,
             Map<String, IContentProvider> providerMap) {
         if (uri == null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
index d1f91d9..ec45b7e 100755
--- a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
@@ -293,6 +293,7 @@
     @Override
     public void draw(Canvas c) {
         final int level = mLevel;
+        final Rect bounds = getBounds();
 
         if (level == -1) return;
 
@@ -301,8 +302,10 @@
         final int width = (int) (getAspectRatio() * mHeight);
         final int px = (mWidth - width) / 2;
         final int buttonHeight = Math.round(height * mButtonHeightFraction);
+        final int left = mPadding.left + bounds.left;
+        final int top = bounds.bottom - mPadding.bottom - height;
 
-        mFrame.set(mPadding.left, mPadding.top, width + mPadding.left, height + mPadding.top);
+        mFrame.set(left, top, width + left, height + top);
         mFrame.offset(px, 0);
 
         // button-frame: area above the battery body
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawable.java b/packages/SettingsLib/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawable.java
index 61790b9..b7fd404 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawable.java
@@ -24,6 +24,7 @@
 import android.graphics.Matrix;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
+import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
@@ -47,7 +48,7 @@
 
     /**
      * Create the {@link LayerDrawable} that contains bluetooth device icon and battery icon.
-     * This is a vertical layout drawable while bluetooth icon at top and battery icon at bottom.
+     * This is a horizontal layout drawable while bluetooth icon at start and battery icon at end.
      *
      * @param context      used to get the spec for icon
      * @param resId        represents the bluetooth device drawable
@@ -55,55 +56,44 @@
      */
     public static BluetoothDeviceLayerDrawable createLayerDrawable(Context context, int resId,
             int batteryLevel) {
+        return createLayerDrawable(context, resId, batteryLevel, 1 /*iconScale*/);
+    }
+
+    /**
+     * Create the {@link LayerDrawable} that contains bluetooth device icon and battery icon.
+     * This is a horizontal layout drawable while bluetooth icon at start and battery icon at end.
+     *
+     * @param context      used to get the spec for icon
+     * @param resId        represents the bluetooth device drawable
+     * @param batteryLevel the battery level for bluetooth device
+     * @param iconScale    the ratio of height between battery icon and bluetooth icon
+     */
+    public static BluetoothDeviceLayerDrawable createLayerDrawable(Context context, int resId,
+            int batteryLevel, float iconScale) {
         final Drawable deviceDrawable = context.getDrawable(resId);
 
         final BatteryMeterDrawable batteryDrawable = new BatteryMeterDrawable(context,
                 R.color.meter_background_color, batteryLevel);
-        final int pad = context.getResources()
-                .getDimensionPixelSize(R.dimen.bt_battery_padding);
-        batteryDrawable.setPadding(0, pad, 0, pad);
+        final int pad = context.getResources().getDimensionPixelSize(R.dimen.bt_battery_padding);
+        batteryDrawable.setPadding(pad, pad, pad, pad);
 
         final BluetoothDeviceLayerDrawable drawable = new BluetoothDeviceLayerDrawable(
-                new Drawable[]{deviceDrawable,
-                        rotateDrawable(context.getResources(), batteryDrawable)});
-        // Set the bluetooth icon at the top
-        drawable.setLayerGravity(0 /* index of deviceDrawable */, Gravity.TOP);
-        // Set battery icon right below the bluetooth icon
-        drawable.setLayerInset(1 /* index of batteryDrawable */, 0,
-                deviceDrawable.getIntrinsicHeight(), 0, 0);
+                new Drawable[]{deviceDrawable, batteryDrawable});
+        // Set the bluetooth icon at the left
+        drawable.setLayerGravity(0 /* index of deviceDrawable */, Gravity.START);
+        // Set battery icon to the right of the bluetooth icon
+        drawable.setLayerInsetStart(1 /* index of batteryDrawable */,
+                deviceDrawable.getIntrinsicWidth());
+        drawable.setLayerInsetTop(1 /* index of batteryDrawable */,
+                (int) (deviceDrawable.getIntrinsicHeight() * (1 - iconScale)));
 
-        drawable.setConstantState(context, resId, batteryLevel);
+        drawable.setConstantState(context, resId, batteryLevel, iconScale);
 
         return drawable;
     }
 
-    /**
-     * Rotate the {@code drawable} by 90 degree clockwise and return rotated {@link Drawable}
-     */
-    private static Drawable rotateDrawable(Resources res, Drawable drawable) {
-        // Get the bitmap from drawable
-        final Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
-                drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
-        final Canvas canvas = new Canvas(bitmap);
-        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
-        drawable.draw(canvas);
-
-        // Create rotate matrix
-        final Matrix matrix = new Matrix();
-        matrix.postRotate(
-                res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_LTR
-                        ? 90 : 270);
-
-        // Create new bitmap with rotate matrix
-        final Bitmap rotateBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
-                bitmap.getHeight(), matrix, true);
-        bitmap.recycle();
-
-        return new BitmapDrawable(res, rotateBitmap);
-    }
-
-    public void setConstantState(Context context, int resId, int batteryLevel) {
-        mState = new BluetoothDeviceLayerDrawableState(context, resId, batteryLevel);
+    public void setConstantState(Context context, int resId, int batteryLevel, float iconScale) {
+        mState = new BluetoothDeviceLayerDrawableState(context, resId, batteryLevel, iconScale);
     }
 
     @Override
@@ -149,17 +139,19 @@
         Context context;
         int resId;
         int batteryLevel;
+        float iconScale;
 
         public BluetoothDeviceLayerDrawableState(Context context, int resId,
-                int batteryLevel) {
+                int batteryLevel, float iconScale) {
             this.context = context;
             this.resId = resId;
             this.batteryLevel = batteryLevel;
+            this.iconScale = iconScale;
         }
 
         @Override
         public Drawable newDrawable() {
-            return createLayerDrawable(context, resId, batteryLevel);
+            return createLayerDrawable(context, resId, batteryLevel, iconScale);
         }
 
         @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
index 00f32b2..56b8441 100644
--- a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
@@ -195,7 +195,7 @@
             intent.setPackage(category.pkg);
         }
         TileUtils.getTilesForIntent(mContext, new UserHandle(UserHandle.myUserId()), intent,
-                mAddCache, null, suggestions, true, false, false);
+                mAddCache, null, suggestions, true, false, false, true /* shouldUpdateTiles */);
         filterSuggestions(suggestions, countBefore, isSmartSuggestionEnabled);
         if (!category.multiple && suggestions.size() > (countBefore + 1)) {
             // If there are too many, remove them all and only re-add the one with the highest
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 0129c66..682b85e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -51,7 +51,6 @@
 import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.TextUtils;
-import android.text.format.DateUtils;
 import android.text.style.TtsSpan;
 import android.util.Log;
 
@@ -133,12 +132,8 @@
      */
     private final Map<String, TimestampedScoredNetwork> mScoredNetworkCache = new HashMap<>();
 
-    /** Maximum age in millis of cached scored networks in {@link #mScoredNetworkCache}. */
-    @VisibleForTesting static final long MAX_CACHED_SCORE_AGE_MILLIS =
-            24 * DateUtils.DAY_IN_MILLIS;
-
     /** Maximum age of scan results to hold onto while actively scanning. **/
-    private static final long MAX_SCAN_RESULT_AGE_MILLIS = 15000;
+    private static final long MAX_SCAN_RESULT_AGE_MILLIS = 25000;
 
     static final String KEY_NETWORKINFO = "key_networkinfo";
     static final String KEY_WIFIINFO = "key_wifiinfo";
@@ -431,6 +426,11 @@
         }
         builder.append(",metered=").append(isMetered());
 
+        if (WifiTracker.sVerboseLogging) {
+            builder.append(",rssi=").append(mRssi);
+            builder.append(",scan cache size=").append(mScanResultCache.size());
+        }
+
         return builder.append(')').toString();
     }
 
@@ -438,13 +438,18 @@
      * Updates the AccessPoint rankingScore, metering, and speed, returning true if the data has
      * changed.
      *
-     * @param scoreCache The score cache to use to retrieve scores.
-     * @param scoringUiEnabled Whether to show scoring and badging UI.
+     * @param scoreCache The score cache to use to retrieve scores
+     * @param scoringUiEnabled Whether to show scoring and badging UI
+     * @param maxScoreCacheAgeMillis the maximum age in milliseconds of scores to consider when
+     *         generating speed labels
      */
-    boolean update(WifiNetworkScoreCache scoreCache, boolean scoringUiEnabled) {
+    boolean update(
+            WifiNetworkScoreCache scoreCache,
+            boolean scoringUiEnabled,
+            long maxScoreCacheAgeMillis) {
         boolean scoreChanged = false;
         if (scoringUiEnabled) {
-            scoreChanged = updateScores(scoreCache);
+            scoreChanged = updateScores(scoreCache, maxScoreCacheAgeMillis);
         }
         return updateMetered(scoreCache) || scoreChanged;
     }
@@ -452,15 +457,18 @@
     /**
      * Updates the AccessPoint rankingScore and speed, returning true if the data has changed.
      *
-     * <p>Any cached {@link TimestampedScoredNetwork} objects older than
-     * {@link #MAX_CACHED_SCORE_AGE_MILLIS} will be removed when this method is invoked.
+     * <p>Any cached {@link TimestampedScoredNetwork} objects older than the given max age in millis
+     * will be removed when this method is invoked.
      *
      * <p>Precondition: {@link #mRssi} is up to date before invoking this method.
      *
-     * @param scoreCache The score cache to use to retrieve scores.
+     * @param scoreCache The score cache to use to retrieve scores
+     * @param maxScoreCacheAgeMillis the maximum age in milliseconds of scores to consider when
+     *         generating speed labels
+     *
      * @return true if the set speed has changed
      */
-    private boolean updateScores(WifiNetworkScoreCache scoreCache) {
+    private boolean updateScores(WifiNetworkScoreCache scoreCache, long maxScoreCacheAgeMillis) {
         long nowMillis = SystemClock.elapsedRealtime();
         for (ScanResult result : mScanResultCache.values()) {
             ScoredNetwork score = scoreCache.getScoredNetwork(result);
@@ -478,7 +486,7 @@
         }
 
         // Remove old cached networks
-        long evictionCutoff = nowMillis - MAX_CACHED_SCORE_AGE_MILLIS;
+        long evictionCutoff = nowMillis - maxScoreCacheAgeMillis;
         Iterator<TimestampedScoredNetwork> iterator = mScoredNetworkCache.values().iterator();
         iterator.forEachRemaining(timestampedScoredNetwork -> {
             if (timestampedScoredNetwork.getUpdatedTimestampMillis() < evictionCutoff) {
@@ -948,6 +956,7 @@
         evictOldScanResults();
 
         // TODO: sort list by RSSI or age
+        long nowMs = SystemClock.elapsedRealtime();
         for (ScanResult result : mScanResultCache.values()) {
             if (result.frequency >= LOWER_FREQ_5GHZ
                     && result.frequency <= HIGHER_FREQ_5GHZ) {
@@ -958,7 +967,7 @@
                     maxRssi5 = result.level;
                 }
                 if (num5 <= maxDisplayedScans) {
-                    scans5GHz.append(verboseScanResultSummary(result, bssid));
+                    scans5GHz.append(verboseScanResultSummary(result, bssid, nowMs));
                 }
             } else if (result.frequency >= LOWER_FREQ_24GHZ
                     && result.frequency <= HIGHER_FREQ_24GHZ) {
@@ -969,7 +978,7 @@
                     maxRssi24 = result.level;
                 }
                 if (num24 <= maxDisplayedScans) {
-                    scans24GHz.append(verboseScanResultSummary(result, bssid));
+                    scans24GHz.append(verboseScanResultSummary(result, bssid, nowMs));
                 }
             }
         }
@@ -997,7 +1006,7 @@
     }
 
     @VisibleForTesting
-    /* package */ String verboseScanResultSummary(ScanResult result, String bssid) {
+    /* package */ String verboseScanResultSummary(ScanResult result, String bssid, long nowMs) {
         StringBuilder stringBuilder = new StringBuilder();
         stringBuilder.append(" \n{").append(result.BSSID);
         if (result.BSSID.equals(bssid)) {
@@ -1010,6 +1019,8 @@
             stringBuilder.append(",")
                     .append(getSpeedLabel(speed));
         }
+        int ageSeconds = (int) (nowMs - result.timestamp / 1000) / 1000;
+        stringBuilder.append(",").append(ageSeconds).append("s");
         stringBuilder.append("}");
         return stringBuilder.toString();
     }
@@ -1206,6 +1217,7 @@
     /** Attempt to update the AccessPoint and return true if an update occurred. */
     public boolean update(
             @Nullable WifiConfiguration config, WifiInfo info, NetworkInfo networkInfo) {
+
         boolean updated = false;
         final int oldLevel = getLevel();
         if (info != null && isInfoForThisAccessPoint(config, info)) {
@@ -1237,6 +1249,7 @@
                 mAccessPointListener.onLevelChanged(this);
             }
         }
+
         return updated;
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/TimestampedScoredNetwork.java b/packages/SettingsLib/src/com/android/settingslib/wifi/TimestampedScoredNetwork.java
index cb15a79..1286d57 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/TimestampedScoredNetwork.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/TimestampedScoredNetwork.java
@@ -33,7 +33,7 @@
     }
 
     protected TimestampedScoredNetwork(Parcel in) {
-        mScore = ScoredNetwork.CREATOR.createFromParcel(in);
+        mScore = in.readParcelable(ScoredNetwork.class.getClassLoader());
         mUpdatedTimestampMillis = in.readLong();
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index a242570..3c664b0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -20,7 +20,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.database.ContentObserver;
 import android.net.ConnectivityManager;
 import android.net.Network;
 import android.net.NetworkCapabilities;
@@ -41,6 +40,7 @@
 import android.os.Message;
 import android.provider.Settings;
 import android.support.annotation.GuardedBy;
+import android.text.format.DateUtils;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.SparseArray;
@@ -65,7 +65,11 @@
  * Tracks saved or available wifi networks and their state.
  */
 public class WifiTracker {
-    // TODO(b/36733768): Remove flag includeSaved and includePasspoints.
+    /**
+     * Default maximum age in millis of cached scored networks in
+     * {@link AccessPoint#mScoredNetworkCache} to be used for speed label generation.
+     */
+    private static final long DEFAULT_MAX_CACHED_SCORE_AGE_MILLIS = 20 * DateUtils.MINUTE_IN_MILLIS;
 
     private static final String TAG = "WifiTracker";
     private static final boolean DBG() {
@@ -76,6 +80,8 @@
      * and used so as to assist with in-the-field WiFi connectivity debugging  */
     public static boolean sVerboseLogging;
 
+    // TODO(b/36733768): Remove flag includeSaved and includePasspoints.
+
     // TODO: Allow control of this?
     // Combo scans can take 5-6s to complete - set to 10s.
     private static final int WIFI_RESCAN_INTERVAL_MS = 10 * 1000;
@@ -138,7 +144,7 @@
     private final NetworkScoreManager mNetworkScoreManager;
     private final WifiNetworkScoreCache mScoreCache;
     private boolean mNetworkScoringUiEnabled;
-    private final ContentObserver mObserver;
+    private long mMaxSpeedLabelScoreCacheAge;
 
     @GuardedBy("mLock")
     private final Set<NetworkKey> mRequestedScores = new ArraySet<>();
@@ -229,16 +235,6 @@
                 updateNetworkScores();
             }
         });
-
-        mObserver = new ContentObserver(mWorkHandler) {
-            @Override
-            public void onChange(boolean selfChange) {
-                mNetworkScoringUiEnabled =
-                        Settings.Global.getInt(
-                                mContext.getContentResolver(),
-                                Settings.Global.NETWORK_SCORING_UI_ENABLED, 0) == 1;
-            }
-        };
     }
 
     /** Synchronously update the list of access points with the latest information. */
@@ -314,11 +310,16 @@
         synchronized (mLock) {
             registerScoreCache();
 
-            mContext.getContentResolver().registerContentObserver(
-                    Settings.Global.getUriFor(Settings.Global.NETWORK_SCORING_UI_ENABLED),
-                    false /* notifyForDescendants */,
-                    mObserver);
-            mObserver.onChange(false /* selfChange */); // Set mScoringUiEnabled
+            mNetworkScoringUiEnabled =
+                    Settings.Global.getInt(
+                            mContext.getContentResolver(),
+                            Settings.Global.NETWORK_SCORING_UI_ENABLED, 0) == 1;
+
+            mMaxSpeedLabelScoreCacheAge =
+                    Settings.Global.getLong(
+                            mContext.getContentResolver(),
+                            Settings.Global.SPEED_LABEL_CACHE_EVICTION_AGE_MILLIS,
+                            DEFAULT_MAX_CACHED_SCORE_AGE_MILLIS);
 
             resumeScanning();
             if (!mRegistered) {
@@ -370,7 +371,6 @@
             }
             unregisterScoreCache();
             pauseScanning();
-            mContext.getContentResolver().unregisterContentObserver(mObserver);
 
             mWorkHandler.removePendingMessages();
             mMainHandler.removePendingMessages();
@@ -609,7 +609,7 @@
 
         requestScoresForNetworkKeys(scoresToRequest);
         for (AccessPoint ap : accessPoints) {
-            ap.update(mScoreCache, mNetworkScoringUiEnabled);
+            ap.update(mScoreCache, mNetworkScoringUiEnabled, mMaxSpeedLabelScoreCacheAge);
         }
 
         // Pre-sort accessPoints to speed preference insertion
@@ -624,7 +624,7 @@
                 String prevSsid = prevAccessPoint.getSsidStr();
                 boolean found = false;
                 for (AccessPoint newAccessPoint : accessPoints) {
-                    if (newAccessPoint.getSsid() != null && newAccessPoint.getSsid()
+                    if (newAccessPoint.getSsidStr() != null && newAccessPoint.getSsidStr()
                             .equals(prevSsid)) {
                         found = true;
                         break;
@@ -676,24 +676,23 @@
     private void updateNetworkInfo(NetworkInfo networkInfo) {
         /* sticky broadcasts can call this when wifi is disabled */
         if (!mWifiManager.isWifiEnabled()) {
-            mMainHandler.sendEmptyMessage(MainHandler.MSG_PAUSE_SCANNING);
             clearAccessPointsAndConditionallyUpdate();
             return;
         }
 
-        if (networkInfo != null &&
-                networkInfo.getDetailedState() == DetailedState.OBTAINING_IPADDR) {
-            mMainHandler.sendEmptyMessage(MainHandler.MSG_PAUSE_SCANNING);
-        } else {
-            mMainHandler.sendEmptyMessage(MainHandler.MSG_RESUME_SCANNING);
-        }
-
         if (networkInfo != null) {
             mLastNetworkInfo = networkInfo;
+            if (DBG()) {
+                Log.d(TAG, "mLastNetworkInfo set: " + mLastNetworkInfo);
+            }
         }
 
         WifiConfiguration connectionConfig = null;
+
         mLastInfo = mWifiManager.getConnectionInfo();
+        if (DBG()) {
+            Log.d(TAG, "mLastInfo set as: " + mLastInfo);
+        }
         if (mLastInfo != null) {
             connectionConfig = getWifiConfigurationForNetworkId(mLastInfo.getNetworkId(),
                     mWifiManager.getConfiguredNetworks());
@@ -710,14 +709,13 @@
                     updated = true;
                     if (previouslyConnected != ap.isActive()) reorder = true;
                 }
-                if (ap.update(mScoreCache, mNetworkScoringUiEnabled)) {
+                if (ap.update(mScoreCache, mNetworkScoringUiEnabled, mMaxSpeedLabelScoreCacheAge)) {
                     reorder = true;
                     updated = true;
                 }
             }
 
             if (reorder) Collections.sort(mInternalAccessPoints);
-
             if (updated) mMainHandler.sendEmptyMessage(MainHandler.MSG_ACCESS_POINT_CHANGED);
         }
     }
@@ -744,7 +742,8 @@
         synchronized (mLock) {
             boolean updated = false;
             for (int i = 0; i < mInternalAccessPoints.size(); i++) {
-                if (mInternalAccessPoints.get(i).update(mScoreCache, mNetworkScoringUiEnabled)) {
+                if (mInternalAccessPoints.get(i).update(
+                        mScoreCache, mNetworkScoringUiEnabled, mMaxSpeedLabelScoreCacheAge)) {
                     updated = true;
                 }
             }
@@ -865,6 +864,9 @@
                     if (mScanner != null) {
                         mScanner.pause();
                     }
+                    synchronized (mLock) {
+                        mStaleScanResults = true;
+                    }
                     break;
             }
         }
@@ -927,6 +929,9 @@
                         if (mScanner != null) {
                             mScanner.pause();
                         }
+                        synchronized (mLock) {
+                            mStaleScanResults = true;
+                        }
                     }
                     mMainHandler.obtainMessage(MainHandler.MSG_WIFI_STATE_CHANGED, msg.arg1, 0)
                             .sendToTarget();
@@ -981,7 +986,7 @@
                 }
                 return;
             }
-            sendEmptyMessageDelayed(0, WIFI_RESCAN_INTERVAL_MS);
+            sendEmptyMessageDelayed(MSG_SCAN, WIFI_RESCAN_INTERVAL_MS);
         }
     }
 
@@ -1074,10 +1079,12 @@
             oldAccessPoints.put(accessPoint.mId, accessPoint);
         }
 
-        if (DBG()) {
-            Log.d(TAG, "Starting to copy AP items on the MainHandler");
-        }
         synchronized (mLock) {
+            if (DBG()) {
+                Log.d(TAG, "Starting to copy AP items on the MainHandler. Internal APs: "
+                        + mInternalAccessPoints);
+            }
+
             if (notifyListeners) {
                 notificationMap = mAccessPointListenerAdapter.mPendingNotifications.clone();
             }
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index b678b3a..230b200 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -45,6 +45,7 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.text.SpannableString;
+import android.text.format.DateUtils;
 import android.text.style.TtsSpan;
 
 import com.android.settingslib.R;
@@ -72,6 +73,8 @@
     private static final RssiCurve FAST_BADGE_CURVE =
             new RssiCurve(-150, 10, new byte[]{Speed.FAST});
     public static final String TEST_BSSID = "00:00:00:00:00:00";
+    private static final long MAX_SCORE_CACHE_AGE_MILLIS =
+            20 * DateUtils.MINUTE_IN_MILLIS;;
 
     private Context mContext;
     @Mock private RssiCurve mockBadgeCurve;
@@ -335,7 +338,8 @@
                                 null /* NetworkKey */,
                                 null /* rssiCurve */,
                                 true /* metered */));
-        ap.update(mockWifiNetworkScoreCache, false /* scoringUiEnabled */);
+        ap.update(mockWifiNetworkScoreCache, false /* scoringUiEnabled */,
+                MAX_SCORE_CACHE_AGE_MILLIS);
 
         assertThat(ap.isMetered()).isTrue();
     }
@@ -364,7 +368,8 @@
                 .thenReturn(buildScoredNetworkWithMockBadgeCurve());
         when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) AccessPoint.Speed.VERY_FAST);
 
-        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
+        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */,
+                MAX_SCORE_CACHE_AGE_MILLIS);
 
         assertThat(ap.getSpeed()).isEqualTo(AccessPoint.Speed.VERY_FAST);
         assertThat(ap.getSpeedLabel())
@@ -379,7 +384,9 @@
                 .thenReturn(buildScoredNetworkWithMockBadgeCurve());
         when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) AccessPoint.Speed.FAST);
 
-        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
+        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */,
+                MAX_SCORE_CACHE_AGE_MILLIS);
+
 
         assertThat(ap.getSpeed()).isEqualTo(AccessPoint.Speed.FAST);
         assertThat(ap.getSpeedLabel())
@@ -394,7 +401,8 @@
                 .thenReturn(buildScoredNetworkWithMockBadgeCurve());
         when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) AccessPoint.Speed.MODERATE);
 
-        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
+        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */,
+                MAX_SCORE_CACHE_AGE_MILLIS);
 
         assertThat(ap.getSpeed()).isEqualTo(AccessPoint.Speed.MODERATE);
         assertThat(ap.getSpeedLabel())
@@ -409,7 +417,8 @@
                 .thenReturn(buildScoredNetworkWithMockBadgeCurve());
         when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) AccessPoint.Speed.SLOW);
 
-        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
+        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */,
+                MAX_SCORE_CACHE_AGE_MILLIS);
 
         assertThat(ap.getSpeed()).isEqualTo(AccessPoint.Speed.SLOW);
         assertThat(ap.getSpeedLabel())
@@ -424,7 +433,8 @@
                 .thenReturn(buildScoredNetworkWithMockBadgeCurve());
         when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) AccessPoint.Speed.VERY_FAST);
 
-        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
+        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */,
+                MAX_SCORE_CACHE_AGE_MILLIS);
 
         assertThat(ap.getSummary()).isEqualTo(mContext.getString(R.string.speed_label_very_fast));
     }
@@ -442,8 +452,9 @@
                 .thenReturn(buildScoredNetworkWithMockBadgeCurve());
         when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) AccessPoint.Speed.VERY_FAST);
 
-        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
-        String summary = ap.verboseScanResultSummary(scanResults.get(0), null);
+        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */,
+                MAX_SCORE_CACHE_AGE_MILLIS);
+        String summary = ap.verboseScanResultSummary(scanResults.get(0), null, 0);
 
         assertThat(summary.contains(mContext.getString(R.string.speed_label_very_fast))).isTrue();
     }
@@ -457,7 +468,8 @@
                 .thenReturn(buildScoredNetworkWithMockBadgeCurve());
         when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) AccessPoint.Speed.VERY_FAST);
 
-        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
+        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */,
+                MAX_SCORE_CACHE_AGE_MILLIS);
 
         String expectedString = mContext.getString(R.string.speed_label_very_fast) + " / "
                 + mContext.getString(R.string.wifi_remembered);
@@ -864,7 +876,8 @@
 
         int expectedSpeed = (speed1 + speed2) / 2;
 
-        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
+        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */,
+                MAX_SCORE_CACHE_AGE_MILLIS);
 
         assertThat(ap.getSpeed()).isEqualTo(expectedSpeed);
     }
@@ -884,7 +897,8 @@
         when(mockWifiNetworkScoreCache.getScoredNetwork(SCAN_RESULTS.get(1)))
                 .thenReturn(buildScoredNetworkWithGivenBadgeCurve(badgeCurve2));
 
-        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
+        ap.update(
+        mockWifiNetworkScoreCache, true /* scoringUiEnabled */, MAX_SCORE_CACHE_AGE_MILLIS);
 
         assertThat(ap.getSpeed()).isEqualTo(speed1);
     }
@@ -925,7 +939,8 @@
         when(mockWifiNetworkScoreCache.getScoredNetwork(scanResultConnected))
                 .thenReturn(null);
 
-        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
+        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */,
+                MAX_SCORE_CACHE_AGE_MILLIS);
 
         assertThat(ap.getSpeed()).isEqualTo(fallbackSpeed);
     }
@@ -952,7 +967,8 @@
         AccessPoint ap =
                 createApWithFastTimestampedScoredNetworkCache(SystemClock.elapsedRealtime());
 
-        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
+        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */,
+                MAX_SCORE_CACHE_AGE_MILLIS);
 
         assertThat(ap.getSpeed()).isEqualTo(Speed.FAST);
     }
@@ -960,11 +976,12 @@
     @Test
     public void testNetworkScoresAreUsedForSpeedLabelGenerationWhenWithinAgeRange() {
         long withinRangeTimeMillis =
-                SystemClock.elapsedRealtime() - (AccessPoint.MAX_CACHED_SCORE_AGE_MILLIS - 10000);
+                SystemClock.elapsedRealtime() - (MAX_SCORE_CACHE_AGE_MILLIS - 10000);
         AccessPoint ap =
                 createApWithFastTimestampedScoredNetworkCache(withinRangeTimeMillis);
 
-        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
+        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */,
+                MAX_SCORE_CACHE_AGE_MILLIS);
 
         assertThat(ap.getSpeed()).isEqualTo(Speed.FAST);
     }
@@ -972,11 +989,12 @@
     @Test
     public void testOldNetworkScoresAreNotUsedForSpeedLabelGeneration() {
         long tooOldTimeMillis =
-                SystemClock.elapsedRealtime() - (AccessPoint.MAX_CACHED_SCORE_AGE_MILLIS + 1);
+                SystemClock.elapsedRealtime() - (MAX_SCORE_CACHE_AGE_MILLIS + 1);
         AccessPoint ap =
                 createApWithFastTimestampedScoredNetworkCache(tooOldTimeMillis);
 
-        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
+        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */,
+                MAX_SCORE_CACHE_AGE_MILLIS);
 
         assertThat(ap.getSpeed()).isEqualTo(Speed.NONE);
     }
@@ -984,7 +1002,7 @@
     @Test
     public void testUpdateScoresRefreshesScoredNetworkCacheTimestamps () {
         long tooOldTimeMillis =
-                SystemClock.elapsedRealtime() - (AccessPoint.MAX_CACHED_SCORE_AGE_MILLIS + 1);
+                SystemClock.elapsedRealtime() - (MAX_SCORE_CACHE_AGE_MILLIS + 1);
 
         ScoredNetwork scoredNetwork = buildScoredNetworkWithGivenBadgeCurve(FAST_BADGE_CURVE);
         TimestampedScoredNetwork recentScore = new TimestampedScoredNetwork(
@@ -1002,7 +1020,8 @@
         when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
                 .thenReturn(scoredNetwork);
 
-        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
+        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */,
+                MAX_SCORE_CACHE_AGE_MILLIS);
 
         // Fast should still be returned since cache was updated with recent time
         assertThat(ap.getSpeed()).isEqualTo(Speed.FAST);
@@ -1011,7 +1030,7 @@
     @Test
     public void testUpdateScoresRefreshesScoredNetworkCacheWithNewSpeed () {
         long tooOldTimeMillis =
-                SystemClock.elapsedRealtime() - (AccessPoint.MAX_CACHED_SCORE_AGE_MILLIS + 1);
+                SystemClock.elapsedRealtime() - (MAX_SCORE_CACHE_AGE_MILLIS + 1);
 
         ScoredNetwork scoredNetwork = buildScoredNetworkWithGivenBadgeCurve(FAST_BADGE_CURVE);
         TimestampedScoredNetwork recentScore = new TimestampedScoredNetwork(
@@ -1031,7 +1050,8 @@
                 .thenReturn(buildScoredNetworkWithMockBadgeCurve());
         when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) newSpeed);
 
-        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
+        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */,
+                MAX_SCORE_CACHE_AGE_MILLIS);
 
         // Fast should still be returned since cache was updated with recent time
         assertThat(ap.getSpeed()).isEqualTo(newSpeed);
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index df6587e..7cce648 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -105,15 +105,30 @@
     private static final byte SCORE_2 = 15;
     private static final int BADGE_2 = AccessPoint.Speed.FAST;
 
-    private static final int CONNECTED_NETWORK_ID = 123;
+    // TODO(b/65594609): Convert mutable Data objects to instance variables / builder pattern
+    private static final int NETWORK_ID_1 = 123;
     private static final int CONNECTED_RSSI = -50;
     private static final WifiInfo CONNECTED_AP_1_INFO = new WifiInfo();
     static {
         CONNECTED_AP_1_INFO.setSSID(WifiSsid.createFromAsciiEncoded(SSID_1));
         CONNECTED_AP_1_INFO.setBSSID(BSSID_1);
-        CONNECTED_AP_1_INFO.setNetworkId(CONNECTED_NETWORK_ID);
+        CONNECTED_AP_1_INFO.setNetworkId(NETWORK_ID_1);
         CONNECTED_AP_1_INFO.setRssi(CONNECTED_RSSI);
     }
+    private static final WifiConfiguration CONFIGURATION_1 = new WifiConfiguration();
+    static {
+        CONFIGURATION_1.SSID = SSID_1;
+        CONFIGURATION_1.BSSID = BSSID_1;
+        CONFIGURATION_1.networkId = NETWORK_ID_1;
+    }
+
+    private static final int NETWORK_ID_2 = 2;
+    private static final WifiConfiguration CONFIGURATION_2 = new WifiConfiguration();
+    static {
+        CONFIGURATION_2.SSID = SSID_2;
+        CONFIGURATION_2.BSSID = BSSID_2;
+        CONFIGURATION_2.networkId = NETWORK_ID_2;
+    }
 
     @Captor ArgumentCaptor<WifiNetworkScoreCache> mScoreCacheCaptor;
     @Mock private ConnectivityManager mockConnectivityManager;
@@ -159,6 +174,8 @@
         when(mockWifiManager.isWifiEnabled()).thenReturn(true);
         when(mockWifiManager.getScanResults())
                 .thenReturn(Arrays.asList(buildScanResult1(), buildScanResult2()));
+        when(mockWifiManager.getConfiguredNetworks())
+                .thenReturn(Arrays.asList(CONFIGURATION_1, CONFIGURATION_2));
 
 
         when(mockCurve1.lookupScore(RSSI_1)).thenReturn(SCORE_1);
@@ -333,8 +350,7 @@
         WifiConfiguration configuration = new WifiConfiguration();
         configuration.SSID = SSID_1;
         configuration.BSSID = BSSID_1;
-        configuration.networkId = CONNECTED_NETWORK_ID;
-        when(mockWifiManager.getConfiguredNetworks()).thenReturn(Arrays.asList(configuration));
+        configuration.networkId = NETWORK_ID_1;
 
         NetworkInfo networkInfo = new NetworkInfo(
                 ConnectivityManager.TYPE_WIFI, 0, "Type Wifi", "subtype");
@@ -365,6 +381,24 @@
                 mainLatch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS));
     }
 
+    private void switchToNetwork2(WifiTracker tracker) throws InterruptedException {
+        NetworkInfo networkInfo = new NetworkInfo(
+                ConnectivityManager.TYPE_WIFI, 0, "Type Wifi", "subtype");
+        networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTING, "connecting", "test");
+
+        WifiInfo info = new WifiInfo();
+        info.setSSID(WifiSsid.createFromAsciiEncoded(SSID_2));
+        info.setBSSID(BSSID_2);
+        info.setRssi(CONNECTED_RSSI);
+        info.setNetworkId(NETWORK_ID_2);
+        when(mockWifiManager.getConnectionInfo()).thenReturn(info);
+
+        Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+        intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, networkInfo);
+        tracker.mReceiver.onReceive(mContext, intent);
+        waitForHandlersToProcessCurrentlyEnqueuedMessages(tracker);
+    }
+
     @Test
     public void testAccessPointListenerSetWhenLookingUpUsingScanResults() {
         ScanResult scanResult = new ScanResult();
@@ -722,12 +756,6 @@
 
         when(mockWifiManager.getConnectionInfo()).thenReturn(CONNECTED_AP_1_INFO);
 
-        WifiConfiguration configuration = new WifiConfiguration();
-        configuration.SSID = SSID_1;
-        configuration.BSSID = BSSID_1;
-        configuration.networkId = CONNECTED_NETWORK_ID;
-        when(mockWifiManager.getConfiguredNetworks()).thenReturn(Arrays.asList(configuration));
-
         NetworkInfo networkInfo = new NetworkInfo(
                 ConnectivityManager.TYPE_WIFI, 0, "Type Wifi", "subtype");
         networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "connected", "test");
@@ -881,4 +909,17 @@
         assertThat(tracker.isConnected()).isFalse();
         verify(mockWifiListener, times(2)).onConnectedChanged();
     }
+
+    @Test
+    public void updateNetworkInfoWithNewConnectedNetwork_switchesNetworks() throws Exception {
+        WifiTracker tracker = createTrackerWithScanResultsAndAccessPoint1Connected();
+
+        switchToNetwork2(tracker);
+
+        List<AccessPoint> aps = tracker.getAccessPoints();
+        assertThat(aps.get(0).getSsidStr()).isEqualTo(SSID_2);
+
+        assertThat(aps.get(0).isReachable()).isTrue();
+        assertThat(aps.get(1).isReachable()).isTrue();
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawableTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawableTest.java
index 89855be..76760a9 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawableTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawableTest.java
@@ -39,6 +39,8 @@
 public class BluetoothDeviceLayerDrawableTest {
     private static final int RES_ID = R.drawable.ic_bt_cellphone;
     private static final int BATTERY_LEVEL = 15;
+    private static final float BATTERY_ICON_SCALE = 0.75f;
+    private static final int BATTERY_ICON_PADDING_TOP = 6;
     private static final float TOLERANCE = 0.001f;
 
     private Context mContext;
@@ -54,9 +56,24 @@
                 mContext, RES_ID, BATTERY_LEVEL);
 
         assertThat(drawable.getDrawable(0)).isInstanceOf(VectorDrawable.class);
-        assertThat(drawable.getDrawable(1)).isInstanceOf(BitmapDrawable.class);
-        assertThat(drawable.getLayerInsetTop(1)).isEqualTo(
-                drawable.getDrawable(0).getIntrinsicHeight());
+        assertThat(drawable.getDrawable(1)).isInstanceOf(
+                BluetoothDeviceLayerDrawable.BatteryMeterDrawable.class);
+        assertThat(drawable.getLayerInsetStart(1)).isEqualTo(
+                drawable.getDrawable(0).getIntrinsicWidth());
+        assertThat(drawable.getLayerInsetTop(1)).isEqualTo(0);
+    }
+
+    @Test
+    public void testCreateLayerDrawable_withIconScale_configCorrect() {
+        BluetoothDeviceLayerDrawable drawable = BluetoothDeviceLayerDrawable.createLayerDrawable(
+                mContext, RES_ID, BATTERY_LEVEL, BATTERY_ICON_SCALE);
+
+        assertThat(drawable.getDrawable(0)).isInstanceOf(VectorDrawable.class);
+        assertThat(drawable.getDrawable(1)).isInstanceOf(
+                BluetoothDeviceLayerDrawable.BatteryMeterDrawable.class);
+        assertThat(drawable.getLayerInsetStart(1)).isEqualTo(
+                drawable.getDrawable(0).getIntrinsicWidth());
+        assertThat(drawable.getLayerInsetTop(1)).isEqualTo(BATTERY_ICON_PADDING_TOP);
     }
 
     @Test
@@ -65,7 +82,7 @@
                 new BluetoothDeviceLayerDrawable.BatteryMeterDrawable(mContext,
                         R.color.meter_background_color, BATTERY_LEVEL);
 
-        assertThat(batteryDrawable.getAspectRatio()).isWithin(TOLERANCE).of(0.45f);
+        assertThat(batteryDrawable.getAspectRatio()).isWithin(TOLERANCE).of(0.35f);
         assertThat(batteryDrawable.getRadiusRatio()).isWithin(TOLERANCE).of(0f);
         assertThat(batteryDrawable.getBatteryLevel()).isEqualTo(BATTERY_LEVEL);
     }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/TimestampedScoredNetworkTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/TimestampedScoredNetworkTest.java
new file mode 100644
index 0000000..639d51c
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/TimestampedScoredNetworkTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.settingslib.wifi;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.net.NetworkKey;
+import android.net.ScoredNetwork;
+import android.net.WifiKey;
+import android.os.Parcel;
+
+import com.android.settingslib.SettingLibRobolectricTestRunner;
+import com.android.settingslib.TestConfig;
+import java.util.Date;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingLibRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class TimestampedScoredNetworkTest {
+  private TimestampedScoredNetwork impl;
+
+  private ScoredNetwork createTestScoredNetwork(String ssid) {
+    return new ScoredNetwork(
+        new NetworkKey(new WifiKey("\"" + ssid + "\"", "00:00:00:00:00:00")), null);
+  }
+
+  @Before
+  public void setUp() {
+    impl = new TimestampedScoredNetwork(createTestScoredNetwork("test"),
+        0 /* updatedTimestampMillis */);
+  }
+
+  @Test
+  public void testUpdate() {
+    long time = new Date().getTime();
+    ScoredNetwork updated = createTestScoredNetwork("updated");
+    impl.update(updated, time);
+
+    assertThat(impl.getScore()).isEqualTo(updated);
+    assertThat(impl.getUpdatedTimestampMillis()).isEqualTo(time);
+  }
+
+  @Test
+  public void testParcel() {
+    Parcel parcel = Parcel.obtain();
+    impl.writeToParcel(parcel, 0);
+    parcel.setDataPosition(0);
+
+    TimestampedScoredNetwork fromParcel = TimestampedScoredNetwork.CREATOR.createFromParcel(parcel);
+
+    assertThat(fromParcel.getScore()).isEqualTo(impl.getScore());
+    assertThat(fromParcel.getUpdatedTimestampMillis()).isEqualTo(impl.getUpdatedTimestampMillis());
+  }
+}
diff --git a/packages/SettingsProvider/res/values-bn/strings.xml b/packages/SettingsProvider/res/values-bn/strings.xml
index 95cb73a..7e72dfb 100644
--- a/packages/SettingsProvider/res/values-bn/strings.xml
+++ b/packages/SettingsProvider/res/values-bn/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4567566098528588863">"সেটিংস সঞ্চয়স্থান"</string>
+    <string name="app_label" msgid="4567566098528588863">"সেটিংস স্টোরেজ"</string>
 </resources>
diff --git a/packages/Shell/res/values-bn/strings.xml b/packages/Shell/res/values-bn/strings.xml
index 07a9df3..56a608d 100644
--- a/packages/Shell/res/values-bn/strings.xml
+++ b/packages/Shell/res/values-bn/strings.xml
@@ -26,8 +26,8 @@
     <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"ত্রুটির প্রতিবেদনটি শেয়ার করতে এটি বেছে নিন"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"আপনার ত্রুটির প্রতিবেদন শেয়ার করতে আলতো চাপ দিন"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"কোনো স্ক্রিনশট ছাড়াই ত্রুটির প্রতিবেদনটি শেয়ার করতে এটি বেছে নিন, বা স্ক্রিনশটের জন্য অপেক্ষা করুন"</string>
-    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"কোনো স্ক্রীনশট ছাড়াই ত্রুটির প্রতিবেদন শেয়ার করতে আলতো চাপ দিন বা সম্পন্ন করতে স্ক্রীনশটের জন্য অপেক্ষা করুন"</string>
-    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"কোনো স্ক্রীনশট ছাড়াই ত্রুটির প্রতিবেদন শেয়ার করতে আলতো চাপ দিন বা সম্পন্ন করতে স্ক্রীনশটের জন্য অপেক্ষা করুন"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"কোনও স্ক্রিনশট ছাড়াই ত্রুটির প্রতিবেদন শেয়ার করতে আলতো চাপ দিন বা সম্পন্ন করতে স্ক্রিনশটের জন্য অপেক্ষা করুন"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"কোনও স্ক্রিনশট ছাড়াই ত্রুটির প্রতিবেদন শেয়ার করতে আলতো চাপ দিন বা সম্পন্ন করতে স্ক্রিনশটের জন্য অপেক্ষা করুন"</string>
     <string name="bugreport_confirm" msgid="5917407234515812495">"ত্রুটির প্রতিবেদনগুলিতে থাকা ডেটা, সিস্টেমের বিভিন্ন লগ ফাইলগুলি থেকে আসে, যাতে আপনার বিবেচনা অনুযায়ী সংবেদনশীল ডেটা (যেমন, অ্যাপ্লিকেশানের ব্যবহার এবং অবস্থান ডেটা) থাকতে পারে৷ আপনি বিশ্বাস করেন শুধুমাত্র এমন অ্যাপ্লিকেশান এবং ব্যক্তিদের সাথেই ত্রুটির প্রতিবেদনগুলিকে শেয়ার করুন৷"</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"আর দেখাবেন না"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"ত্রুটির প্রতিবেদনগুলি"</string>
@@ -35,13 +35,13 @@
     <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"জিপ ফাইলে ত্রুটি প্রতিবেদনের বিশদ বিবরণ যোগ করা যায়নি"</string>
     <string name="bugreport_unnamed" msgid="2800582406842092709">"নামবিহীন"</string>
     <string name="bugreport_info_action" msgid="2158204228510576227">"বিশদ বিবরণ"</string>
-    <string name="bugreport_screenshot_action" msgid="8677781721940614995">"স্ক্রীনশট"</string>
-    <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"স্ক্রীনশট সফলভাবে নেওয়া হয়েছে৷"</string>
-    <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"স্ক্রীনশট নেওয়া যায়নি৷"</string>
+    <string name="bugreport_screenshot_action" msgid="8677781721940614995">"স্ক্রিনশট"</string>
+    <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"স্ক্রিনশট সফলভাবে নেওয়া হয়েছে৷"</string>
+    <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"স্ক্রিনশট নেওয়া যায়নি৷"</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ত্রুটির প্রতিবেদন <xliff:g id="ID">#%d</xliff:g> এর বিশদ বিবরণ"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"ফাইলের নাম"</string>
     <string name="bugreport_info_title" msgid="2306030793918239804">"ত্রুটির শীর্ষক"</string>
     <string name="bugreport_info_description" msgid="5072835127481627722">"ত্রুটির সারাংশ"</string>
-    <string name="save" msgid="4781509040564835759">"সংরক্ষণ করুন"</string>
+    <string name="save" msgid="4781509040564835759">"সেভ করুন"</string>
     <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"ত্রুটির প্রতিবেদন শেয়ার করুন"</string>
 </resources>
diff --git a/packages/Shell/res/values-hi/strings.xml b/packages/Shell/res/values-hi/strings.xml
index c82284c..666d254 100644
--- a/packages/Shell/res/values-hi/strings.xml
+++ b/packages/Shell/res/values-hi/strings.xml
@@ -28,7 +28,7 @@
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"स्क्रीनशॉट के बिना अपनी गड़बड़ी की रिपोर्ट शेयर करना चुनें या स्क्रीनशॉट पूरा होने तक इंतज़ार करें"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"अपनी गड़बड़ी की रिपोर्ट को बिना स्क्रीनशॉट के शेयर करने के लिए टैप करें या स्क्रीनशॉट पूरा होने की इंतज़ार करें"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"अपनी गड़बड़ी की रिपोर्ट को बिना स्क्रीनशॉट के शेयर करने के लिए टैप करें या स्क्रीनशॉट पूरा होने की इंतज़ार करें"</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"गड़बड़ी की रिपोर्ट में सिस्टम की अलग-अलग लॉग फ़ाइलों का डेटा शामिल होता है, जिसमें ऐसा डेटा शामिल हो सकता है जिसे आप संवेदनशील मानते हैं (जैसे कि ऐप्लिकेशन का उपयोग और स्थान डेटा). गड़बड़ी की रिपोर्ट केवल अपने भरोसेमंद लोगों और ऐप्लिकेशन से साझा करें."</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"गड़बड़ी की रिपोर्ट में सिस्टम की अलग-अलग लॉग फ़ाइलों का डेटा शामिल होता है, जिसमें ऐसा डेटा शामिल हो सकता है जिसे आप संवेदनशील मानते हैं (जैसे कि ऐप्लिकेशन का उपयोग और जगह डेटा). गड़बड़ी की रिपोर्ट केवल अपने भरोसेमंद लोगों और ऐप्लिकेशन से शेयर करें."</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"फिर से ना दिखाएं"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"गड़बड़ी की रिपोर्ट"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"गड़बड़ी की रिपोर्ट फ़ाइल नहीं पढ़ी जा सकी"</string>
@@ -42,6 +42,6 @@
     <string name="bugreport_info_name" msgid="4414036021935139527">"फ़ाइल नाम"</string>
     <string name="bugreport_info_title" msgid="2306030793918239804">"गड़बड़ी का शीर्षक"</string>
     <string name="bugreport_info_description" msgid="5072835127481627722">"गड़बड़ी का सारांश"</string>
-    <string name="save" msgid="4781509040564835759">"सहेजें"</string>
+    <string name="save" msgid="4781509040564835759">"सेव करें"</string>
     <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"गड़बड़ी की रिपोर्ट शेयर करें"</string>
 </resources>
diff --git a/packages/Shell/res/values-iw/strings.xml b/packages/Shell/res/values-iw/strings.xml
index 5accb77..c99e69e 100644
--- a/packages/Shell/res/values-iw/strings.xml
+++ b/packages/Shell/res/values-iw/strings.xml
@@ -42,6 +42,6 @@
     <string name="bugreport_info_name" msgid="4414036021935139527">"שם קובץ"</string>
     <string name="bugreport_info_title" msgid="2306030793918239804">"כותרת הבאג"</string>
     <string name="bugreport_info_description" msgid="5072835127481627722">"סיכום הבאג"</string>
-    <string name="save" msgid="4781509040564835759">"שמור"</string>
+    <string name="save" msgid="4781509040564835759">"שמירה"</string>
     <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"שיתוף דוח על באג"</string>
 </resources>
diff --git a/packages/Shell/res/values-pa/strings.xml b/packages/Shell/res/values-pa/strings.xml
index 56a2bea..cdf3769 100644
--- a/packages/Shell/res/values-pa/strings.xml
+++ b/packages/Shell/res/values-pa/strings.xml
@@ -22,14 +22,14 @@
     <string name="bugreport_finished_title" msgid="4429132808670114081">"ਬੱਗ ਰਿਪੋਰਟ <xliff:g id="ID">#%d</xliff:g> ਕੈਪਚਰ ਕੀਤੀ ਗਈ"</string>
     <string name="bugreport_updating_title" msgid="4423539949559634214">"ਬੱਗ ਰਿਪੋਰਟ ਵਿੱਚ ਵੇਰਵਿਆਂ ਨੂੰ ਸ਼ਾਮਲ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
     <string name="bugreport_updating_wait" msgid="3322151947853929470">"ਕਿਰਪਾ ਕਰਕੇ ਉਡੀਕ ਕਰੋ..."</string>
-    <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"ਬੱਗ ਰਿਪੋਰਟ ਜਲਦ ਹੀ ਫ਼ੋਨ \'ਤੇ ਵਿਖਾਈ ਦੇਵੇਗੀ"</string>
+    <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"ਬੱਗ ਰਿਪੋਰਟ ਜਲਦ ਹੀ ਫ਼ੋਨ \'ਤੇ ਦਿਖਾਈ ਦੇਵੇਗੀ"</string>
     <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"ਆਪਣੀ ਬੱਗ ਰਿਪੋਰਟ ਨੂੰ ਸਾਂਝਾ ਕਰਨ ਲਈ ਚੁਣੋ"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"ਆਪਣੀ ਬੱਗ ਰਿਪੋਰਟ ਸਾਂਝੀ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇ ਬਿਨਾਂ ਆਪਣੀ ਬੱਗ ਰਿਪੋਰਟ ਨੂੰ ਸਾਂਝਾ ਕਰਨ ਲਈ ਚੁਣੋ ਜਾਂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇ ਪੂਰੇ ਹੋਣ ਦੀ ਉਡੀਕ ਕਰੋ"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇ ਬਿਨਾਂ ਆਪਣੀ ਬੱਗ ਰਿਪੋਰਟ ਨੂੰ ਸਾਂਝੀ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ ਜਾਂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇ ਪੂਰੇ ਹੋਣ ਦੀ ਉਡੀਕ ਕਰੋ"</string>
     <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇ ਬਿਨਾਂ ਆਪਣੀ ਬੱਗ ਰਿਪੋਰਟ ਨੂੰ ਸਾਂਝੀ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ ਜਾਂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇ ਪੂਰੇ ਹੋਣ ਦੀ ਉਡੀਕ ਕਰੋ"</string>
-    <string name="bugreport_confirm" msgid="5917407234515812495">"ਬੱਗ ਰਿਪੋਰਟਾਂ ਵਿੱਚ ਸਿਸਟਮ ਦੀਆਂ ਵੱਖ-ਵੱਖ ਲੌਗ ਫ਼ਾਈਲਾਂ ਦਾ ਡੈਟਾ ਸ਼ਾਮਲ ਹੁੰਦਾ ਹੈ, ਜਿਸ ਵਿੱਚ ਉਹ ਡੈਟਾ ਸ਼ਾਮਲ ਹੋ ਸਕਦਾ ਹੈ ਜਿਸ ਨੂੰ ਤੁਸੀਂ ਸੰਵੇਦਨਸ਼ੀਲ ਮੰਨਦੇ ਹੋ (ਜਿਵੇਂ ਕਿ ਐਪ-ਵਰਤੋਂ ਅਤੇ ਟਿਕਾਣਾ ਡੈਟਾ)। ਬੱਗ ਰਿਪੋਰਟਾਂ ਨੂੰ ਸਿਰਫ਼ ਆਪਣੇ ਭਰੋਸੇਯੋਗ ਲੋਕਾਂ ਅਤੇ ਐਪਾਂ ਨਾਲ ਸਾਂਝਾ ਕਰੋ।"</string>
-    <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"ਦੁਬਾਰਾ ਨਾ ਵਿਖਾਓ"</string>
+    <string name="bugreport_confirm" msgid="5917407234515812495">"ਬੱਗ ਰਿਪੋਰਟਾਂ ਵਿੱਚ ਸਿਸਟਮ ਦੀਆਂ ਵੱਖ-ਵੱਖ ਲੌਗ ਫ਼ਾਈਲਾਂ ਦਾ ਡਾਟਾ ਸ਼ਾਮਲ ਹੁੰਦਾ ਹੈ, ਜਿਸ ਵਿੱਚ ਉਹ ਡਾਟਾ ਸ਼ਾਮਲ ਹੋ ਸਕਦਾ ਹੈ ਜਿਸ ਨੂੰ ਤੁਸੀਂ ਸੰਵੇਦਨਸ਼ੀਲ ਮੰਨਦੇ ਹੋ (ਜਿਵੇਂ ਕਿ ਐਪ-ਵਰਤੋਂ ਅਤੇ ਟਿਕਾਣਾ ਡਾਟਾ)। ਬੱਗ ਰਿਪੋਰਟਾਂ ਨੂੰ ਸਿਰਫ਼ ਆਪਣੇ ਭਰੋਸੇਯੋਗ ਲੋਕਾਂ ਅਤੇ ਐਪਾਂ ਨਾਲ ਸਾਂਝਾ ਕਰੋ।"</string>
+    <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"ਦੁਬਾਰਾ ਨਾ  ਦਿਖਾਓ"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"ਬਗ ਰਿਪੋਰਟਾਂ"</string>
     <string name="bugreport_unreadable_text" msgid="586517851044535486">"ਬਗ ਰਿਪੋਰਟ ਫ਼ਾਈਲ ਪੜ੍ਹੀ ਨਹੀਂ ਜਾ ਸਕੀ"</string>
     <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"ਬੱਗ ਰਿਪੋਰਟ ਵੇਰਵਿਆਂ ਨੂੰ ਜ਼ਿਪ ਫ਼ਾਈਲ ਵਿੱਚ ਸ਼ਾਮਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index c997160..070634b 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -318,15 +318,20 @@
             android:exported="false">
         </activity>
 
+        <!-- Springboard for launching the share activity -->
+        <receiver android:name=".screenshot.GlobalScreenshot$ShareReceiver"
+            android:process=":screenshot"
+            android:exported="false" />
+
         <!-- Callback for dismissing screenshot notification after a share target is picked -->
         <receiver android:name=".screenshot.GlobalScreenshot$TargetChosenReceiver"
-                  android:process=":screenshot"
-                  android:exported="false" />
+            android:process=":screenshot"
+            android:exported="false" />
 
         <!-- Callback for deleting screenshot notification -->
         <receiver android:name=".screenshot.GlobalScreenshot$DeleteScreenshotReceiver"
-                  android:process=":screenshot"
-                  android:exported="false" />
+            android:process=":screenshot"
+            android:exported="false" />
 
         <!-- started from UsbDeviceSettingsManager -->
         <activity android:name=".usb.UsbConfirmActivity"
diff --git a/packages/SystemUI/res-keyguard/values-bn/strings.xml b/packages/SystemUI/res-keyguard/values-bn/strings.xml
index 2c58f77..24d00cc 100644
--- a/packages/SystemUI/res-keyguard/values-bn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bn/strings.xml
@@ -77,20 +77,20 @@
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8637788033282252027">"আপনি আপনার পিন টাইপ করতে <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল করেছেন৷ \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন৷"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7724148763268377734">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে আপনার পাসওয়ার্ড লিখেছেন।\n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন।"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4820967667848302092">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে আপনার আনলকের প্যাটার্ন এঁকেছেন।\n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন।"</string>
-    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1629351522209932316">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে ট্যাবলেটটি আনলক করার চেষ্টা করেছেন। আরো <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর এই ট্যাবলেটটিকে রিসেট করা হবে, যার ফলে এর সমস্ত ডেটা মুছে যাবে।"</string>
-    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="3921998703529189931">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে ফোনটি আনলক করার চেষ্টা করেছেন। আরো <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর এই ফোনটিকে রিসেট করা হবে, যার ফলে এর সমস্ত ডেটা মুছে যাবে।"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1629351522209932316">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে ট্যাবলেটটি আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর এই ট্যাবলেটটিকে রিসেট করা হবে, যার ফলে এর সমস্ত ডেটা মুছে যাবে।"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="3921998703529189931">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে ফোনটি আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর এই ফোনটিকে রিসেট করা হবে, যার ফলে এর সমস্ত ডেটা মুছে যাবে।"</string>
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="4694232971224663735">"আপনি <xliff:g id="NUMBER">%d</xliff:g> বার ভুলভাবে ট্যাবলেটটি আনলক করার চেষ্টা করেছেন। এই ফোনটিকে রিসেট করা হবে, যার ফলে এর সমস্ত ডেটা মুছে যাবে।"</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="2365964340830006961">"আপনি <xliff:g id="NUMBER">%d</xliff:g> বার ভুলভাবে ফোনটি আনলক করার চেষ্টা করেছেন। এই ফোনটিকে রিসেট করা হবে, যার ফলে এর সমস্ত ডেটা মুছে যাবে।"</string>
-    <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="1365418870560228936">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে ট্যাবলেটটি আনলক করার চেষ্টা করেছেন। আরো <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর এই ব্যবহারকারীকে সরিয়ে দেওয়া হবে, যার ফলে ব্যবহারকারীর সমস্ত ডেটা মুছে যাবে।"</string>
-    <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="2151286957817486128">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে ফোনটি আনলক করার চেষ্টা করেছেন। আরো <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর এই ব্যবহারকারীকে সরিয়ে দেওয়া হবে, যার ফলে ব্যবহারকারীর সমস্ত ডেটা মুছে যাবে।"</string>
+    <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="1365418870560228936">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে ট্যাবলেটটি আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর এই ব্যবহারকারীকে সরিয়ে দেওয়া হবে, যার ফলে ব্যবহারকারীর সমস্ত ডেটা মুছে যাবে।"</string>
+    <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="2151286957817486128">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে ফোনটি আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর এই ব্যবহারকারীকে সরিয়ে দেওয়া হবে, যার ফলে ব্যবহারকারীর সমস্ত ডেটা মুছে যাবে।"</string>
     <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="5464020754932560928">"আপনি <xliff:g id="NUMBER">%d</xliff:g> বার ভুলভাবে ট্যাবলেটটি আনলক করার চেষ্টা করেছেন। এই ব্যবহারকারীকে সরিয়ে দেওয়া হবে, যার ফলে ব্যবহারকারীর সমস্ত ডেটা মুছে যাবে।"</string>
     <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="6171564974118059">"আপনি <xliff:g id="NUMBER">%d</xliff:g> বার ভুলভাবে ফোনটি আনলক করার চেষ্টা করেছেন। এই ব্যবহারকারীকে সরিয়ে দেওয়া হবে, যার ফলে ব্যবহারকারীর সমস্ত ডেটা মুছে যাবে।"</string>
-    <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="9154513795928824239">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে ট্যাবলেটটি আনলক করার চেষ্টা করেছেন। আরো <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর কাজের প্রোফাইলটি সরিয়ে দেওয়া হবে, যার ফলে প্রোফাইলের সমস্ত ডেটা মুছে যাবে।"</string>
-    <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="2162434417489128282">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে ফোনটি আনলক করার চেষ্টা করেছেন। আরো <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর কাজের প্রোফাইলটি সরিয়ে দেওয়া হবে, যার ফলে প্রোফাইলের সমস্ত ডেটা মুছে যাবে।"</string>
+    <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="9154513795928824239">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে ট্যাবলেটটি আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর কাজের প্রোফাইলটি সরিয়ে দেওয়া হবে, যার ফলে প্রোফাইলের সমস্ত ডেটা মুছে যাবে।"</string>
+    <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="2162434417489128282">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে ফোনটি আনলক করার চেষ্টা করেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর কাজের প্রোফাইলটি সরিয়ে দেওয়া হবে, যার ফলে প্রোফাইলের সমস্ত ডেটা মুছে যাবে।"</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="8966727588974691544">"আপনি <xliff:g id="NUMBER">%d</xliff:g> বার ভুলভাবে ট্যাবলেটটি আনলক করার চেষ্টা করেছেন। কাজের প্রোফাইলটি সরিয়ে দেওয়া হবে, যার ফলে প্রোফাইলের সমস্ত ডেটা মুছে যাবে।"</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="8476407539834855">"আপনি <xliff:g id="NUMBER">%d</xliff:g> বার ভুলভাবে ফোনটি আনলক করার চেষ্টা করেছেন। কাজের প্রোফাইলটি সরিয়ে দেওয়া হবে, যার ফলে প্রোফাইলের সমস্ত ডেটা মুছে যাবে।"</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে আনলকের প্যাটার্ন এঁকেছেন। আরো <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর আপনাকে একটি ইমেল অ্যাকাউন্টের মাধ্যমে আপনার ট্যাবলেটটি আনলক করতে বলা হবে।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন।"</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে আনলকের প্যাটার্ন এঁকেছেন। আরো <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর আপনাকে একটি ইমেল অ্যাকাউন্টের মাধ্যমে আপনার ফোনটি আনলক করতে বলা হবে।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন।"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে আনলকের প্যাটার্ন এঁকেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর আপনাকে একটি ইমেল অ্যাকাউন্টের মাধ্যমে আপনার ট্যাবলেটটি আনলক করতে বলা হবে।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন।"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে আনলকের প্যাটার্ন এঁকেছেন। আরও <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টার পর আপনাকে একটি ইমেল অ্যাকাউন্টের মাধ্যমে আপনার ফোনটি আনলক করতে বলা হবে।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন।"</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"ভুল সিম পিন কোড দিয়েছেন, আপনার ডিভাইসটি আনলক করতে এখন আপনাকে অবশ্যই আপনার পরিষেবা প্রদানকারীর সাথে যোগাযোগ করতে হবে।"</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="4314341367727055967">
       <item quantity="one">সিমের পিন কোডটি ভুল, আপনি আর <xliff:g id="NUMBER_1">%d</xliff:g> বার চেষ্টা করতে পারেন।</item>
diff --git a/packages/SystemUI/res-keyguard/values-el/strings.xml b/packages/SystemUI/res-keyguard/values-el/strings.xml
index d195c87..6b9f47c 100644
--- a/packages/SystemUI/res-keyguard/values-el/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-el/strings.xml
@@ -56,7 +56,7 @@
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"Ξεχάσατε το μοτίβο"</string>
     <string name="kg_wrong_pattern" msgid="7620081431514773802">"Λάθος μοτίβο"</string>
     <string name="kg_wrong_password" msgid="4580683060277329277">"Λανθασμένος κωδικός πρόσβασης"</string>
-    <string name="kg_wrong_pin" msgid="4785660766909463466">"Λανθασμένος αριθμός PIN"</string>
+    <string name="kg_wrong_pin" msgid="4785660766909463466">"Λανθασμένο PIN"</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="527455490371878356">"Δοκιμάστε ξανά σε <xliff:g id="NUMBER">%d</xliff:g> δευτερόλεπτα."</string>
     <string name="kg_pattern_instructions" msgid="5547646893001491340">"Σχεδιάστε το μοτίβο σας"</string>
     <string name="kg_sim_pin_instructions" msgid="6389000973113699187">"Εισαγωγή αριθμού PIN κάρτας SIM"</string>
@@ -108,13 +108,13 @@
     <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"Εναλλαγή μεθόδου εισαγωγής"</string>
     <string name="airplane_mode" msgid="3807209033737676010">"Λειτουργία πτήσης"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="7246972020562621506">"Απαιτείται μοτίβο μετά από την επανεκκίνηση της συσκευής"</string>
-    <string name="kg_prompt_reason_restart_pin" msgid="6303592361322290145">"Απαιτείται αριθμός PIN μετά από την επανεκκίνηση της συσκευής"</string>
+    <string name="kg_prompt_reason_restart_pin" msgid="6303592361322290145">"Απαιτείται PIN μετά από την επανεκκίνηση της συσκευής"</string>
     <string name="kg_prompt_reason_restart_password" msgid="6984641181515902406">"Απαιτείται κωδικός πρόσβασης μετά από την επανεκκίνηση της συσκευής"</string>
     <string name="kg_prompt_reason_timeout_pattern" msgid="5304487696073914063">"Απαιτείται μοτίβο για πρόσθετη ασφάλεια"</string>
-    <string name="kg_prompt_reason_timeout_pin" msgid="8851462864335757813">"Απαιτείται αριθμός PIN για πρόσθετη ασφάλεια"</string>
+    <string name="kg_prompt_reason_timeout_pin" msgid="8851462864335757813">"Απαιτείται PIN για πρόσθετη ασφάλεια"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="6563904839641583441">"Απαιτείται κωδικός πρόσβασης για πρόσθετη ασφάλεια"</string>
     <string name="kg_prompt_reason_switch_profiles_pattern" msgid="3398054847288438444">"Απαιτείται μοτίβο κατά την εναλλαγή προφίλ"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="7426368139226961699">"Απαιτείται αριθμός PIN κατά την εναλλαγή προφίλ"</string>
+    <string name="kg_prompt_reason_switch_profiles_pin" msgid="7426368139226961699">"Απαιτείται PIN κατά την εναλλαγή προφίλ"</string>
     <string name="kg_prompt_reason_switch_profiles_password" msgid="8383831046318421845">"Απαιτείται κωδικός πρόσβασης κατά την εναλλαγή προφίλ"</string>
     <string name="kg_prompt_reason_device_admin" msgid="3452168247888906179">"Η συσκευή κλειδώθηκε από τον διαχειριστή"</string>
     <string name="kg_prompt_reason_user_request" msgid="8236951765212462286">"Η συσκευή κλειδώθηκε με μη αυτόματο τρόπο"</string>
diff --git a/packages/SystemUI/res-keyguard/values-gu/strings.xml b/packages/SystemUI/res-keyguard/values-gu/strings.xml
index 8e5a7d29..c04dad8 100644
--- a/packages/SystemUI/res-keyguard/values-gu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gu/strings.xml
@@ -23,7 +23,7 @@
     <string name="app_name" msgid="3171996292755059205">"કીગાર્ડ"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3420548423949593123">"પિન કોડ લખો"</string>
     <string name="keyguard_password_enter_puk_code" msgid="670683628782925409">"સિમ PUK અને નવો પિન કોડ લખો"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3747778500166059332">"SIM PUK કોડ"</string>
+    <string name="keyguard_password_enter_puk_prompt" msgid="3747778500166059332">"સિમ PUK કોડ"</string>
     <string name="keyguard_password_enter_pin_prompt" msgid="8188243197504453830">"નવો સિમ પિન કોડ"</string>
     <string name="keyguard_password_entry_touch_hint" msgid="5790410752696806482"><font size="17">"પાસવર્ડ લખવા માટે સ્પર્શ કરો"</font></string>
     <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"અનલૉક કરવા માટે પાસવર્ડ લખો"</string>
@@ -48,7 +48,7 @@
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="3586601150825821675">"સિમ કાર્ડ અનલૉક કરી રહ્યાં છીએ…"</string>
     <string name="keyguard_accessibility_pin_area" msgid="703175752097279029">"પિન ક્ષેત્ર"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="912702510825058921">"સિમ પિન ક્ષેત્ર"</string>
-    <string name="keyguard_accessibility_sim_puk_area" msgid="136979425761438705">"SIM PUK ક્ષેત્ર"</string>
+    <string name="keyguard_accessibility_sim_puk_area" msgid="136979425761438705">"સિમ PUK ક્ષેત્ર"</string>
     <string name="keyguard_accessibility_next_alarm" msgid="5835196989158584991">"<xliff:g id="ALARM">%1$s</xliff:g> માટે આગલું એલાર્મ સેટ કર્યું"</string>
     <string name="keyboardview_keycode_delete" msgid="6883116827512721630">"કાઢી નાખો"</string>
     <string name="disable_carrier_button_text" msgid="6914341927421916114">"eSIMને અક્ષમ કરો"</string>
@@ -64,14 +64,14 @@
     <string name="kg_sim_lock_instructions_esim" msgid="4957650659201013804">"મોબાઇલ સેવા વગર ઉપકરણનો ઉપયોગ કરવા eSIMને અક્ષમ કરો."</string>
     <string name="kg_pin_instructions" msgid="4069609316644030034">"પિન દાખલ કરો"</string>
     <string name="kg_password_instructions" msgid="136952397352976538">"પાસવર્ડ દાખલ કરો"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"SIM હમણાં અક્ષમ કરેલ છે. ચાલુ રાખવા માટે PUK કોડ દાખલ કરો. વિગતો માટે કૅરિઅરનો સંપર્ક કરો."</string>
-    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" હમણાં અક્ષમ કરેલ છે. ચાલુ રાખવા માટે PUK કોડ દાખલ કરો. વિગતો માટે કૅરિઅરનો સંપર્ક કરો."</string>
+    <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"સિમ હમણાં અક્ષમ કરેલ છે. ચાલુ રાખવા માટે PUK કોડ દાખલ કરો. વિગતો માટે કૅરિઅરનો સંપર્ક કરો."</string>
+    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"સિમ \"<xliff:g id="CARRIER">%1$s</xliff:g>\" હમણાં અક્ષમ કરેલ છે. ચાલુ રાખવા માટે PUK કોડ દાખલ કરો. વિગતો માટે કૅરિઅરનો સંપર્ક કરો."</string>
     <string name="kg_puk_enter_pin_hint" msgid="3137789674920391087">"જોઈતો પિન કોડ દાખલ કરો"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="3089485999116759671">"જોઈતા પિન કોડની પુષ્ટિ કરો"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4471738151810900114">"સિમ કાર્ડ અનલૉક કરી રહ્યાં છીએ…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="3057533256729513335">"4 થી 8 સંખ્યાનો હોય તેવો એક પિન લખો."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="6003602401368264144">"PUK કોડ 8 કે તેનાથી વધુ સંખ્યાનો હોવો જોઈએ."</string>
-    <string name="kg_invalid_puk" msgid="5399287873762592502">"સાચો PUK કોડ ફરીથી દાખલ કરો. પુનરાવર્તિત પ્રયાસો SIM ને કાયમી રીતે અક્ષમ કરશે."</string>
+    <string name="kg_invalid_puk" msgid="5399287873762592502">"સાચો PUK કોડ ફરીથી દાખલ કરો. પુનરાવર્તિત પ્રયાસો સિમ ને કાયમી રીતે અક્ષમ કરશે."</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="5672736555427444330">"પિન કોડ મેળ ખાતા નથી"</string>
     <string name="kg_login_too_many_attempts" msgid="6604574268387867255">"ઘણા બધા પૅટર્ન પ્રયાસો"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8637788033282252027">"તમારો પિન તમે <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે લખ્યો છે. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> સેકન્ડમાં ફરીથી પ્રયાસ કરો."</string>
@@ -96,13 +96,13 @@
       <item quantity="one">ખોટો સિમ પિન કોડ, તમારી પાસે <xliff:g id="NUMBER_1">%d</xliff:g> પ્રયાસ બાકી છે.</item>
       <item quantity="other">ખોટો સિમ પિન કોડ, તમારી પાસે <xliff:g id="NUMBER_1">%d</xliff:g> પ્રયાસ બાકી છે.</item>
     </plurals>
-    <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"SIM અનુપયોગી છે. તમારા કૅરિઅરનો સંપર્ક કરો."</string>
+    <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"સિમ અનુપયોગી છે. તમારા કૅરિઅરનો સંપર્ક કરો."</string>
     <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="2287504898931957513">
-      <item quantity="one">ખોટો SIM PUK કોડ, SIM કાયમી રૂપે અનુપયોગી બની જાય તે પહેલા તમારી પાસે <xliff:g id="NUMBER_1">%d</xliff:g> પ્રયાસ બાકી છે.</item>
-      <item quantity="other">ખોટો SIM PUK કોડ, SIM કાયમી રૂપે અનુપયોગી બની જાય તે પહેલા તમારી પાસે <xliff:g id="NUMBER_1">%d</xliff:g> પ્રયાસ બાકી છે.</item>
+      <item quantity="one">ખોટો સિમ PUK કોડ, સિમ કાયમી રૂપે અનુપયોગી બની જાય તે પહેલા તમારી પાસે <xliff:g id="NUMBER_1">%d</xliff:g> પ્રયાસ બાકી છે.</item>
+      <item quantity="other">ખોટો સિમ PUK કોડ, સિમ કાયમી રૂપે અનુપયોગી બની જાય તે પહેલા તમારી પાસે <xliff:g id="NUMBER_1">%d</xliff:g> પ્રયાસ બાકી છે.</item>
     </plurals>
     <string name="kg_password_pin_failed" msgid="8769990811451236223">"સિમ પિન ઑપરેશન નિષ્ફળ થયું!"</string>
-    <string name="kg_password_puk_failed" msgid="1331621440873439974">"SIM PUK ઓપરેશન નિષ્ફળ થયું!"</string>
+    <string name="kg_password_puk_failed" msgid="1331621440873439974">"સિમ PUK ઓપરેશન નિષ્ફળ થયું!"</string>
     <string name="kg_pin_accepted" msgid="7637293533973802143">"કોડ સ્વીકાર્યો!"</string>
     <string name="keyguard_carrier_default" msgid="4274828292998453695">"કોઈ સેવા નથી."</string>
     <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"ઇનપુટ પદ્ધતિ સ્વિચ કરો"</string>
diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml
index 5e9bf3c..83f11f3 100644
--- a/packages/SystemUI/res-keyguard/values-hi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml
@@ -42,7 +42,7 @@
     <string name="keyguard_missing_sim_instructions" msgid="7350295932015220392">"SIM कार्ड लगाएं."</string>
     <string name="keyguard_missing_sim_instructions_long" msgid="589889372883904477">"SIM कार्ड मौजूद नहीं है या उसे पढ़ा नहीं जा सकता है. कोई SIM कार्ड लगाएं."</string>
     <string name="keyguard_permanent_disabled_sim_message_short" msgid="654102080186420706">"बेकार SIM कार्ड."</string>
-    <string name="keyguard_permanent_disabled_sim_instructions" msgid="4683178224791318347">"आपका SIM कार्ड हमेशा के लिए अक्षम कर दिया गया है.\n दूसरे SIM कार्ड के लिए अपने वायरलेस सेवा प्रदाता से संपर्क करें."</string>
+    <string name="keyguard_permanent_disabled_sim_instructions" msgid="4683178224791318347">"आपका सिम कार्ड हमेशा के लिए बंद कर दिया गया है.\n दूसरे सिम कार्ड के लिए अपने वायरलेस सेवा देने वाले से संपर्क करें."</string>
     <string name="keyguard_sim_locked_message" msgid="953766009432168127">"SIM कार्ड लॉक किया हुआ है."</string>
     <string name="keyguard_sim_puk_locked_message" msgid="1772789643694942073">"SIM कार्ड को PUK के ज़रिए लॉक किया हुआ है."</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="3586601150825821675">"SIM कार्ड अनलॉक हो रहा है…"</string>
@@ -50,7 +50,7 @@
     <string name="keyguard_accessibility_sim_pin_area" msgid="912702510825058921">"SIM पिन क्षेत्र"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="136979425761438705">"SIM PUK क्षेत्र"</string>
     <string name="keyguard_accessibility_next_alarm" msgid="5835196989158584991">"अगला अलार्म <xliff:g id="ALARM">%1$s</xliff:g> बजे के लिए सेट किया गया है"</string>
-    <string name="keyboardview_keycode_delete" msgid="6883116827512721630">"हटाएं"</string>
+    <string name="keyboardview_keycode_delete" msgid="6883116827512721630">"मिटाएं"</string>
     <string name="disable_carrier_button_text" msgid="6914341927421916114">"eSIM अक्षम करें"</string>
     <string name="keyboardview_keycode_enter" msgid="4505833604411016668">"Enter"</string>
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"पैटर्न भूल गए हैं"</string>
diff --git a/packages/SystemUI/res-keyguard/values-mr/strings.xml b/packages/SystemUI/res-keyguard/values-mr/strings.xml
index 7fcc7b6..814603c 100644
--- a/packages/SystemUI/res-keyguard/values-mr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mr/strings.xml
@@ -61,7 +61,7 @@
     <string name="kg_pattern_instructions" msgid="5547646893001491340">"तुमचा पॅटर्न काढा"</string>
     <string name="kg_sim_pin_instructions" msgid="6389000973113699187">"सिम पिन एंटर करा"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="1643757228644271861">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" साठी सिम पिन एंटर करा"</string>
-    <string name="kg_sim_lock_instructions_esim" msgid="4957650659201013804">"मोबाइल सेवांशिवाय डीव्हाइस वापरण्यासाठी eSIM बंद करा."</string>
+    <string name="kg_sim_lock_instructions_esim" msgid="4957650659201013804">"मोबाइल सेवांशिवाय डिव्हाइस वापरण्यासाठी eSIM बंद करा."</string>
     <string name="kg_pin_instructions" msgid="4069609316644030034">"पिन प्रविष्ट करा"</string>
     <string name="kg_password_instructions" msgid="136952397352976538">"संकेतशब्द प्रविष्ट करा"</string>
     <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"सिम आता अक्षम केले आहे. सुरू ठेवण्यासाठी PUK कोड प्रविष्ट करा. तपशीलांसाठी वाहकाशी संपर्क साधा."</string>
@@ -91,7 +91,7 @@
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="8476407539834855">"आपण फोन अनलॉक करण्याचा <xliff:g id="NUMBER">%d</xliff:g> वेळा चुकीच्या पद्धतीने प्रयत्न केला आहे. कार्य प्रोफाइल काढली जाईल, जे सर्व प्रोफाइल डेटा हटवेल."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"तुम्ही आपला अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यपणे काढला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, तुमच्याला ईमेल खाते वापरून आपला टॅब्लेट अनलॉक करण्यास सांगितले जाईल.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"तुम्ही आपला अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यपणे काढला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, तुमच्याला ईमेल खाते वापरून आपला फोन अनलॉक करण्यास सांगितले जाईल.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
-    <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"सिम पिन कोड चुकीचा आहे तुम्ही आता तुमचे डीव्हाइस अनलॉक करण्‍यासाठी तुमच्या वाहकाशी संपर्क साधावा."</string>
+    <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"सिम पिन कोड चुकीचा आहे तुम्ही आता तुमचे डिव्हाइस अनलॉक करण्‍यासाठी तुमच्या वाहकाशी संपर्क साधावा."</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="4314341367727055967">
       <item quantity="one">चुकीचा सिम पिन कोड, तुमच्याकडे <xliff:g id="NUMBER_1">%d</xliff:g> प्रयत्न शिल्लक आहेत.</item>
       <item quantity="other">चुकीचा सिम पिन कोड, तुमच्याकडे <xliff:g id="NUMBER_1">%d</xliff:g> प्रयत्न शिल्लक आहेत.</item>
@@ -107,28 +107,28 @@
     <string name="keyguard_carrier_default" msgid="4274828292998453695">"सेवा नाही."</string>
     <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"इनपुट पद्धत स्विच करा"</string>
     <string name="airplane_mode" msgid="3807209033737676010">"विमान मोड"</string>
-    <string name="kg_prompt_reason_restart_pattern" msgid="7246972020562621506">"डीव्हाइस रीस्टार्ट झाल्यावर पॅटर्न आवश्यक आहे"</string>
-    <string name="kg_prompt_reason_restart_pin" msgid="6303592361322290145">"डीव्हाइस रीस्टार्ट झाल्यावर पिन आवश्यक आहे"</string>
-    <string name="kg_prompt_reason_restart_password" msgid="6984641181515902406">"डीव्हाइस रीस्टार्ट झाल्यावर पासवर्ड आवश्यक आहे"</string>
+    <string name="kg_prompt_reason_restart_pattern" msgid="7246972020562621506">"डिव्हाइस रीस्टार्ट झाल्यावर पॅटर्न आवश्यक आहे"</string>
+    <string name="kg_prompt_reason_restart_pin" msgid="6303592361322290145">"डिव्हाइस रीस्टार्ट झाल्यावर पिन आवश्यक आहे"</string>
+    <string name="kg_prompt_reason_restart_password" msgid="6984641181515902406">"डिव्हाइस रीस्टार्ट झाल्यावर पासवर्ड आवश्यक आहे"</string>
     <string name="kg_prompt_reason_timeout_pattern" msgid="5304487696073914063">"अतिरिक्त सुरक्षिततेसाठी पॅटर्न आवश्‍यक आहे"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="8851462864335757813">"अतिरिक्त सुरक्षिततेसाठी पिन आवश्‍यक आहे"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="6563904839641583441">"अतिरिक्त सुरक्षिततेसाठी संकेतशब्द आवश्‍यक आहे"</string>
     <string name="kg_prompt_reason_switch_profiles_pattern" msgid="3398054847288438444">"तुम्ही प्रोफाईल स्विच करता तेव्‍हा पॅटर्न आवश्‍यक आहे"</string>
     <string name="kg_prompt_reason_switch_profiles_pin" msgid="7426368139226961699">"आपण प्रोफाईल स्विच करता तेव्‍हा पिन आवश्‍यक आहे"</string>
     <string name="kg_prompt_reason_switch_profiles_password" msgid="8383831046318421845">"आपण प्रोफाईल स्विच करता तेव्‍हा संकेतशब्द आवश्‍यक आहे"</string>
-    <string name="kg_prompt_reason_device_admin" msgid="3452168247888906179">"प्रशासकाद्वारे लॉक केलेले डीव्हाइस"</string>
-    <string name="kg_prompt_reason_user_request" msgid="8236951765212462286">"डीव्हाइस मॅन्युअली लॉक केले होते"</string>
+    <string name="kg_prompt_reason_device_admin" msgid="3452168247888906179">"प्रशासकाद्वारे लॉक केलेले डिव्हाइस"</string>
+    <string name="kg_prompt_reason_user_request" msgid="8236951765212462286">"डिव्हाइस मॅन्युअली लॉक केले होते"</string>
     <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="71299470072448533">
-      <item quantity="one">डीव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासासाठी अनलॉक केले गेले नाही. पॅटर्नची खात्री करा.</item>
-      <item quantity="other">डीव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासांसाठी अनलॉक केले गेले नाही. पॅटर्नची खात्री करा.</item>
+      <item quantity="one">डिव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासासाठी अनलॉक केले गेले नाही. पॅटर्नची खात्री करा.</item>
+      <item quantity="other">डिव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासांसाठी अनलॉक केले गेले नाही. पॅटर्नची खात्री करा.</item>
     </plurals>
     <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="34586942088144385">
-      <item quantity="one">डीव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासासाठी अनलॉक केले गेले नाही. पिनची खात्री करा.</item>
-      <item quantity="other">डीव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासांसाठी अनलॉक केले गेले नाही. पिन ची खात्री करा.</item>
+      <item quantity="one">डिव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासासाठी अनलॉक केले गेले नाही. पिनची खात्री करा.</item>
+      <item quantity="other">डिव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासांसाठी अनलॉक केले गेले नाही. पिन ची खात्री करा.</item>
     </plurals>
     <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="257297696215346527">
-      <item quantity="one">डीव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासासाठी अनलॉक केले गेले नाही. पासवर्डची खात्री करा.</item>
-      <item quantity="other">डीव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासांसाठी अनलॉक केले गेले नाही. पासवर्डची खात्री करा.</item>
+      <item quantity="one">डिव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासासाठी अनलॉक केले गेले नाही. पासवर्डची खात्री करा.</item>
+      <item quantity="other">डिव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासांसाठी अनलॉक केले गेले नाही. पासवर्डची खात्री करा.</item>
     </plurals>
     <string name="fingerprint_not_recognized" msgid="348813995267914625">"ओळखले नाही"</string>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml
index 358d022..6ef3f38 100644
--- a/packages/SystemUI/res-keyguard/values-pa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml
@@ -23,26 +23,26 @@
     <string name="app_name" msgid="3171996292755059205">"ਕੀ-ਗਾਰਡ"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3420548423949593123">"ਪਿੰਨ ਕੋਡ ਟਾਈਪ ਕਰੋ"</string>
     <string name="keyguard_password_enter_puk_code" msgid="670683628782925409">"ਸਿਮ PUK ਅਤੇ ਨਵਾਂ ਪਿੰਨ ਕੋਡ ਟਾਈਪ ਕਰੋ"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3747778500166059332">"SIM PUK ਕੋਡ"</string>
+    <string name="keyguard_password_enter_puk_prompt" msgid="3747778500166059332">"ਸਿਮ PUK ਕੋਡ"</string>
     <string name="keyguard_password_enter_pin_prompt" msgid="8188243197504453830">"ਨਵਾਂ ਸਿਮ ਪਿੰਨ ਕੋਡ"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="5790410752696806482"><font size="17">"ਪਾਸਵਰਡ ਟਾਈਪ ਕਰਨ ਲਈ ਸਪੱਰਸ਼ ਕਰੋ"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"ਅਨਲੌਕ ਕਰਨ ਲਈ ਪਾਸਵਰਡ ਟਾਈਪ ਕਰੋ"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"ਅਨਲੌਕ ਕਰਨ ਲਈ ਪਿੰਨ ਟਾਈਪ ਕਰੋ"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ਗ਼ਲਤ ਪਿੰਨ ਕੋਡ।"</string>
+    <string name="keyguard_password_entry_touch_hint" msgid="5790410752696806482"><font size="17">"ਪਾਸਵਰਡ ਟਾਈਪ ਕਰਨ ਲਈ ਸਪਰਸ਼ ਕਰੋ"</font></string>
+    <string name="keyguard_password_enter_password_code" msgid="595980919238127672">"ਅਣਲਾਕ ਕਰਨ ਲਈ ਪਾਸਵਰਡ ਟਾਈਪ ਕਰੋ"</string>
+    <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"ਅਣਲਾਕ ਕਰਨ ਲਈ ਪਿੰਨ ਟਾਈਪ ਕਰੋ"</string>
+    <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"ਗਲਤ ਪਿੰਨ ਕੋਡ।"</string>
     <string name="keyguard_charged" msgid="2222329688813033109">"ਚਾਰਜ ਹੋ ਗਿਆ"</string>
     <string name="keyguard_plugged_in" msgid="89308975354638682">"ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="8869226755413795173">"ਤੇਜ਼ੀ ਨਾਲ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="6637043106038550407">"ਹੌਲੀ-ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="keyguard_low_battery" msgid="9218432555787624490">"ਆਪਣਾ ਚਾਰਜਰ ਕਨੈਕਟ ਕਰੋ।"</string>
-    <string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"ਅਨਲੌਕ ਕਰਨ ਲਈ \'ਮੀਨੂ\' ਦਬਾਓ।"</string>
+    <string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"ਅਣਲਾਕ ਕਰਨ ਲਈ \"ਮੀਨੂ\" ਦਬਾਓ।"</string>
     <string name="keyguard_network_locked_message" msgid="6743537524631420759">"ਨੈੱਟਵਰਕ ਲੌਕ ਕੀਤਾ ਗਿਆ"</string>
-    <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"ਕੋਈ SIM ਕਾਰਡ ਮੌਜੂਦ ਨਹੀਂ"</string>
-    <string name="keyguard_missing_sim_message" product="tablet" msgid="4550152848200783542">"ਟੈਬਲੈੱਟ ਵਿੱਚ ਕੋਈ SIM ਕਾਰਡ ਮੌਜੂਦ ਨਹੀਂ।"</string>
-    <string name="keyguard_missing_sim_message" product="default" msgid="6585414237800161146">"ਫ਼ੋਨ ਵਿੱਚ ਕੋਈ SIM ਕਾਰਡ ਮੌਜੂਦ ਨਹੀਂ।"</string>
+    <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"ਕੋਈ ਸਿਮ ਕਾਰਡ ਨਹੀਂ"</string>
+    <string name="keyguard_missing_sim_message" product="tablet" msgid="4550152848200783542">"ਟੈਬਲੈੱਟ ਵਿੱਚ ਕੋਈ ਸਿਮ ਕਾਰਡ ਮੌਜੂਦ ਨਹੀਂ।"</string>
+    <string name="keyguard_missing_sim_message" product="default" msgid="6585414237800161146">"ਫ਼ੋਨ ਵਿੱਚ ਕੋਈ ਸਿਮ ਕਾਰਡ ਮੌਜੂਦ ਨਹੀਂ।"</string>
     <string name="keyguard_missing_sim_instructions" msgid="7350295932015220392">"ਇੱਕ SIM ਕਾਰਡ ਪਾਓ।"</string>
     <string name="keyguard_missing_sim_instructions_long" msgid="589889372883904477">"SIM ਕਾਰਡ ਮੌਜੂਦ ਨਹੀਂ ਜਾਂ ਪੜ੍ਹਨਯੋਗ ਨਹੀਂ ਹੈ। ਇੱਕ SIM ਕਾਰਡ ਪਾਓ।"</string>
     <string name="keyguard_permanent_disabled_sim_message_short" msgid="654102080186420706">"ਨਾ-ਵਰਤਣਯੋਗ SIM ਕਾਰਡ।"</string>
-    <string name="keyguard_permanent_disabled_sim_instructions" msgid="4683178224791318347">"ਤੁਹਾਡਾ SIM ਕਾਰਡ ਸਥਾਈ ਤੌਰ \'ਤੇ ਅਯੋਗ ਬਣਾ ਦਿੱਤਾ ਗਿਆ ਹੈ।\n ਇੱਕ ਹੋਰ SIM ਕਾਰਡ ਲਈ ਆਪਣੇ ਵਾਇਰਲੈੱਸ ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
+    <string name="keyguard_permanent_disabled_sim_instructions" msgid="4683178224791318347">"ਤੁਹਾਡਾ ਸਿਮ ਕਾਰਡ ਸਥਾਈ ਤੌਰ \'ਤੇ ਅਯੋਗ ਬਣਾ ਦਿੱਤਾ ਗਿਆ ਹੈ।\n ਇੱਕ ਹੋਰ ਸਿਮ ਕਾਰਡ ਲਈ ਆਪਣੇ ਵਾਇਰਲੈੱਸ ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
     <string name="keyguard_sim_locked_message" msgid="953766009432168127">"SIM ਕਾਰਡ ਲੌਕ ਕੀਤਾ ਹੋਇਆ ਹੈ।"</string>
     <string name="keyguard_sim_puk_locked_message" msgid="1772789643694942073">"SIM ਕਾਰਡ PUK-ਲੌਕ ਕੀਤਾ ਹੋਇਆ ਹੈ।"</string>
     <string name="keyguard_sim_unlock_progress_dialog_message" msgid="3586601150825821675">"SIM ਕਾਰਡ ਨੂੰ ਅਨਲੌਕ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
@@ -56,56 +56,56 @@
     <string name="kg_forgot_pattern_button_text" msgid="534245177645252620">"ਪੈਟਰਨ ਭੁੱਲ ਗਏ"</string>
     <string name="kg_wrong_pattern" msgid="7620081431514773802">"ਗਲਤ ਪੈਟਰਨ"</string>
     <string name="kg_wrong_password" msgid="4580683060277329277">"ਗਲਤ ਪਾਸਵਰਡ"</string>
-    <string name="kg_wrong_pin" msgid="4785660766909463466">"ਗ਼ਲਤ ਪਿੰਨ"</string>
+    <string name="kg_wrong_pin" msgid="4785660766909463466">"ਗਲਤ ਪਿੰਨ"</string>
     <string name="kg_too_many_failed_attempts_countdown" msgid="527455490371878356">"<xliff:g id="NUMBER">%d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="kg_pattern_instructions" msgid="5547646893001491340">"ਆਪਣਾ ਪੈਟਰਨ ਉਲੀਕੋ"</string>
     <string name="kg_sim_pin_instructions" msgid="6389000973113699187">"ਸਿਮ ਪਿੰਨ ਦਾਖਲ ਕਰੋ।"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="1643757228644271861">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" ਲਈ ਸਿਮ ਪਿੰਨ ਦਾਖਲ ਕਰੋ।"</string>
-    <string name="kg_sim_lock_instructions_esim" msgid="4957650659201013804">"ਮੋਬਾਈਲ ਸੇਵਾ ਤੋਂ ਬਿਨਾਂ ਡੀਵਾਈਸ ਨੂੰ ਵਰਤਣ ਲਈ eSIM ਅਯੋਗ ਬਣਾਓ।"</string>
+    <string name="kg_sim_lock_instructions_esim" msgid="4957650659201013804">"ਮੋਬਾਈਲ ਸੇਵਾ ਤੋਂ ਬਿਨਾਂ ਡੀਵਾਈਸ ਨੂੰ ਵਰਤਣ ਲਈ eSIM ਬੰਦ ਕਰੋ।"</string>
     <string name="kg_pin_instructions" msgid="4069609316644030034">"ਪਿੰਨ ਦਾਖਲ ਕਰੋ"</string>
     <string name="kg_password_instructions" msgid="136952397352976538">"ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ"</string>
-    <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"SIM ਹੁਣ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ। ਜਾਰੀ ਰੱਖਣ ਲਈ PUK ਕੋਡ ਦਾਖਲ ਕਰੋ। ਵੇਰਵਿਆਂ ਲਈ ਕੈਰੀਅਰ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string>
-    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" ਹੁਣ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ। ਜਾਰੀ ਰੱਖਣ ਲਈ PUK ਕੋਡ ਦਾਖਲ ਕਰੋ। ਵੇਰਵਿਆਂ ਲਈ ਕੈਰੀਅਰ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string>
+    <string name="kg_puk_enter_puk_hint" msgid="2288964170039899277">"ਸਿਮ ਹੁਣ ਬੰਦ ਕੀਤਾ ਗਿਆ ਹੈ। ਜਾਰੀ ਰੱਖਣ ਲਈ PUK ਕੋਡ ਦਾਖਲ ਕਰੋ। ਵੇਰਵਿਆਂ ਲਈ ਕੈਰੀਅਰ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string>
+    <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"ਸਿਮ \"<xliff:g id="CARRIER">%1$s</xliff:g>\" ਹੁਣ ਬੰਦ ਕੀਤਾ ਗਿਆ ਹੈ। ਜਾਰੀ ਰੱਖਣ ਲਈ PUK ਕੋਡ ਦਾਖਲ ਕਰੋ। ਵੇਰਵਿਆਂ ਲਈ ਕੈਰੀਅਰ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string>
     <string name="kg_puk_enter_pin_hint" msgid="3137789674920391087">"ਇੱਛਤ ਪਿੰਨ ਕੋਡ ਦਾਖਲ ਕਰੋ"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="3089485999116759671">"ਇੱਛਤ ਪਿੰਨ ਕੋਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ"</string>
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4471738151810900114">"SIM ਕਾਰਡ ਨੂੰ ਅਨਲੌਕ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="3057533256729513335">"ਕੋਈ ਪਿੰਨ ਟਾਈਪ ਕਰੋ ਜੋ 4 ਤੋਂ 8 ਨੰਬਰਾਂ ਦਾ ਹੋਵੇ।"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="6003602401368264144">"PUK ਕੋਡ 8 ਜਾਂ ਵੱਧ ਨੰਬਰਾਂ ਦਾ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ।"</string>
-    <string name="kg_invalid_puk" msgid="5399287873762592502">"ਸਹੀ PUK ਕੋਡ ਮੁੜ-ਦਾਖਲ ਕਰੋ। ਬਾਰ-ਬਾਰ ਕੀਤੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ SIM ਨੂੰ ਸਥਾਈ ਤੌਰ \'ਤੇ ਅਯੋਗ ਬਣਾ ਦੇਣਗੀਆਂ।"</string>
+    <string name="kg_invalid_puk" msgid="5399287873762592502">"ਸਹੀ PUK ਕੋਡ ਮੁੜ-ਦਾਖਲ ਕਰੋ। ਬਾਰ-ਬਾਰ ਕੀਤੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ ਸਿਮ ਨੂੰ ਸਥਾਈ ਤੌਰ \'ਤੇ ਬੰਦ ਕਰ ਦੇਣਗੀਆਂ।"</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="5672736555427444330">"ਪਿੰਨ ਕੋਡ ਮੇਲ ਨਹੀਂ ਖਾਂਦੇ"</string>
     <string name="kg_login_too_many_attempts" msgid="6604574268387867255">"ਬਹੁਤ ਜ਼ਿਆਦਾ ਪੈਟਰਨ ਕੋਸ਼ਿਸ਼ਾਂ"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8637788033282252027">"ਤੁਸੀਂ ਆਪਣਾ ਪਿੰਨ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗ਼ਲਤ ਢੰਗ ਨਾਲ ਟਾਈਪ ਕੀਤਾ ਹੈ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8637788033282252027">"ਤੁਸੀਂ ਆਪਣਾ ਪਿੰਨ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟਾਈਪ ਕੀਤਾ ਹੈ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7724148763268377734">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਪਾਸਵਰਡ ਗਲਤ ਢੰਗ ਨਾਲ ਟਾਈਪ ਕੀਤਾ ਹੈ।\n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
-    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4820967667848302092">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਨਲੌਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ ਹੈ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
-    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1629351522209932316">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਹ ਟੈਬਲੈੱਟ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="3921998703529189931">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਹ ਫ਼ੋਨ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="4694232971224663735">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਇਹ ਟੈਬਲੈੱਟ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_now_wiping" product="default" msgid="2365964340830006961">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਇਹ ਫ਼ੋਨ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="1365418870560228936">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="2151286957817486128">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="5464020754932560928">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="6171564974118059">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="9154513795928824239">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਪ੍ਰੋਫਾਈਲ ਦਾ ਸਾਰਾ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="2162434417489128282">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਪ੍ਰੋਫਾਈਲ ਦਾ ਸਾਰਾ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="8966727588974691544">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਪ੍ਰੋਫਾਈਲ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="8476407539834855">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਪ੍ਰੋਫਾਈਲ ਡੈਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਨਲੌਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣੇ ਟੈਬਲੈੱਟ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਵੇਗਾ।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਨਲੌਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣਾ ਫ਼ੋਨ ਅਨਲੌਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਵੇਗਾ।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
-    <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"ਗ਼ਲਤ ਸਿਮ ਪਿੰਨ ਕੋਡ, ਆਪਣੇ ਡੀਵਾਈਸ ਨੂੰ ਅਨਲੌਕ ਕਰਨ ਲਈ ਹੁਣ ਤੁਹਾਨੂੰ ਲਾਜ਼ਮੀ ਤੌਰ \'ਤੇ ਆਪਣੇ ਕੈਰੀਅਰ ਨਾਲ ਸੰਪਰਕ ਕਰਨਾ ਚਾਹੀਦਾ ਹੈ।"</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4820967667848302092">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ ਹੈ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1629351522209932316">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਹ ਟੈਬਲੈੱਟ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="3921998703529189931">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਹ ਫ਼ੋਨ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="4694232971224663735">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਇਹ ਟੈਬਲੈੱਟ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="2365964340830006961">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਇਹ ਫ਼ੋਨ ਰੀਸੈੱਟ ਕੀਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਇਸਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="1365418870560228936">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="2151286957817486128">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="5464020754932560928">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="6171564974118059">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਇਸ ਵਰਤੋਂਕਾਰ ਨੂੰ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਵਰਤੋਂਕਾਰ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="9154513795928824239">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਪ੍ਰੋਫਾਈਲ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="2162434417489128282">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਪ੍ਰੋਫਾਈਲ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="8966727588974691544">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਪ੍ਰੋਫਾਈਲ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="8476407539834855">"ਤੁਸੀਂ <xliff:g id="NUMBER">%d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਫ਼ੋਨ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕੀਤੀ ਹੈ। ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਹਟਾ ਦਿੱਤਾ ਜਾਵੇਗਾ, ਜਿਸ ਨਾਲ ਸਾਰਾ ਪ੍ਰੋਫਾਈਲ ਡਾਟਾ ਮਿਟ ਜਾਵੇਗਾ।"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="956706236554092172">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣੇ ਟੈਬਲੈੱਟ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਵੇਗਾ।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਡ੍ਰਾ ਕੀਤਾ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣਾ ਫ਼ੋਨ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਏਗਾ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"ਗਲਤ ਸਿਮ ਪਿੰਨ ਕੋਡ, ਆਪਣੇ ਡੀਵਾਈਸ ਨੂੰ ਅਣਲਾਕ ਕਰਨ ਲਈ ਹੁਣ ਤੁਹਾਨੂੰ ਲਾਜ਼ਮੀ ਤੌਰ \'ਤੇ ਆਪਣੇ ਕੈਰੀਅਰ ਨਾਲ ਸੰਪਰਕ ਕਰਨਾ ਚਾਹੀਦਾ ਹੈ।"</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="4314341367727055967">
-      <item quantity="one">ਗ਼ਲਤ ਸਿਮ ਪਿੰਨ ਕੋਡ, ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ ਬਾਕੀ ਹੈ।</item>
-      <item quantity="other">ਗ਼ਲਤ ਸਿਮ ਪਿੰਨ ਕੋਡ, ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ਾਂ ਬਾਕੀ ਹਨ।</item>
+      <item quantity="one">ਗਲਤ ਸਿਮ ਪਿੰਨ ਕੋਡ, ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ ਬਾਕੀ ਹੈ।</item>
+      <item quantity="other">ਗਲਤ ਸਿਮ ਪਿੰਨ ਕੋਡ, ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ ਬਾਕੀ ਹੈ।</item>
     </plurals>
     <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"SIM ਨਾ-ਵਰਤਣਯੋਗ ਹੈ। ਆਪਣੇ ਕੈਰੀਅਰ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
     <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="2287504898931957513">
-      <item quantity="one">ਗਲਤ SIM PUK ਕੋਡ, ਇਸਤੋਂ ਪਹਿਲਾਂ ਕਿ SIM ਸਥਾਈ ਤੌਰ \'ਤੇ ਵਰਤਣਯੋਗ ਨਾ ਰਹੇ, ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ ਬਾਕੀ ਹੈ।</item>
-      <item quantity="other">ਗਲਤ SIM PUK ਕੋਡ, ਇਸਤੋਂ ਪਹਿਲਾਂ ਕਿ SIM ਸਥਾਈ ਤੌਰ \'ਤੇ ਵਰਤਣਯੋਗ ਨਾ ਰਹੇ, ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ਾਂ ਬਾਕੀ ਹਨ।</item>
+      <item quantity="one">ਗਲਤ ਸਿਮ PUK ਕੋਡ, ਇਸਤੋਂ ਪਹਿਲਾਂ ਕਿ ਸਿਮ ਸਥਾਈ ਤੌਰ \'ਤੇ ਵਰਤਣਯੋਗ ਨਾ ਰਹੇ, ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ ਬਾਕੀ ਹੈ।</item>
+      <item quantity="other">ਗਲਤ ਸਿਮ PUK ਕੋਡ, ਇਸਤੋਂ ਪਹਿਲਾਂ ਕਿ ਸਿਮ ਸਥਾਈ ਤੌਰ \'ਤੇ ਵਰਤਣਯੋਗ ਨਾ ਰਹੇ, ਤੁਹਾਡੇ ਕੋਲ <xliff:g id="NUMBER_1">%d</xliff:g> ਕੋਸ਼ਿਸ਼ਾਂ ਬਾਕੀ ਹਨ।</item>
     </plurals>
     <string name="kg_password_pin_failed" msgid="8769990811451236223">"ਸਿਮ ਪਿੰਨ ਕਾਰਵਾਈ ਅਸਫਲ ਰਹੀ!"</string>
     <string name="kg_password_puk_failed" msgid="1331621440873439974">"SIM PUK ਕਾਰਵਾਈ ਅਸਫਲ ਰਹੀ!"</string>
     <string name="kg_pin_accepted" msgid="7637293533973802143">"ਕੋਡ ਸਵੀਕਾਰ ਕੀਤਾ ਗਿਆ!"</string>
     <string name="keyguard_carrier_default" msgid="4274828292998453695">"ਕੋਈ ਸੇਵਾ ਨਹੀਂ।"</string>
-    <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"ਇਨਪੁੱਟ ਵਿਧੀ ਬਦਲੋ"</string>
+    <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"ਇਨਪੁੱਟ ਵਿਧੀ ਸਵਿੱਚ ਕਰੋ"</string>
     <string name="airplane_mode" msgid="3807209033737676010">"ਹਵਾਈ-ਜਹਾਜ਼ ਮੋਡ"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="7246972020562621506">"ਡੀਵਾਈਸ ਦੇ ਮੁੜ-ਚਾਲੂ ਹੋਣ \'ਤੇ ਪੈਟਰਨ ਦੀ ਲੋੜ ਹੈ"</string>
     <string name="kg_prompt_reason_restart_pin" msgid="6303592361322290145">"ਡੀਵਾਈਸ ਦੇ ਮੁੜ-ਚਾਲੂ ਹੋਣ \'ਤੇ ਪਿੰਨ ਦੀ ਲੋੜ ਹੈ"</string>
@@ -113,22 +113,22 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="5304487696073914063">"ਵਧੀਕ ਸੁਰੱਖਿਆ ਲਈ ਪੈਟਰਨ ਦੀ ਲੋੜ ਹੈ"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="8851462864335757813">"ਵਧੀਕ ਸੁਰੱਖਿਆ ਲਈ ਪਿੰਨ ਦੀ ਲੋੜ ਹੈ"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="6563904839641583441">"ਵਧੀਕ ਸੁਰੱਖਿਆ ਲਈ ਪਾਸਵਰਡ ਦੀ ਲੋੜ ਹੈ"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="3398054847288438444">"ਜਦ ਤੁਸੀਂ ਇੱਕ ਪ੍ਰੋਫਾਈਲ ਤੋਂ ਦੂਜੇ \'ਤੇ ਜਾਂਦੇ ਹੋ ਤਾਂ ਪੈਟਰਨ ਦੀ ਲੋੜ ਹੈ"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="7426368139226961699">"ਜਦ ਤੁਸੀਂ ਇੱਕ ਪ੍ਰੋਫਾਈਲ ਤੋਂ ਦੂਜੇ \'ਤੇ ਜਾਂਦੇ ਹੋ ਤਾਂ ਪਿੰਨ ਦੀ ਲੋੜ ਹੈ"</string>
+    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="3398054847288438444">"ਜਦ ਤੁਸੀਂ ਪ੍ਰੋਫਾਈਲਾਂ ਨੂੰ ਸਵਿੱਚ ਕਰਦੇ ਹੋ ਤਾਂ ਪੈਟਰਨ ਦੀ ਲੋੜ ਹੈ"</string>
+    <string name="kg_prompt_reason_switch_profiles_pin" msgid="7426368139226961699">"ਜਦ ਤੁਸੀਂ ਪ੍ਰੋਫਾਈਲਾਂ ਨੂੰ ਸਵਿੱਚ ਕਰਦੇ ਹੋ ਤਾਂ ਪਿੰਨ ਦੀ ਲੋੜ ਹੈ"</string>
     <string name="kg_prompt_reason_switch_profiles_password" msgid="8383831046318421845">"ਜਦ ਤੁਸੀਂ ਇੱਕ ਪ੍ਰੋਫਾਈਲ ਤੋਂ ਦੂਜੇ \'ਤੇ ਜਾਂਦੇ ਹੋ ਤਾਂ ਪਾਸਵਰਡ ਦੀ ਲੋੜ ਹੈ"</string>
-    <string name="kg_prompt_reason_device_admin" msgid="3452168247888906179">"ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਡੀਵਾਈਸ ਨੂੰ ਲੌਕ ਕੀਤਾ ਗਿਆ"</string>
-    <string name="kg_prompt_reason_user_request" msgid="8236951765212462286">"ਡੀਵਾਈਸ ਨੂੰ ਹੱਥੀਂ ਲੌਕ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="kg_prompt_reason_device_admin" msgid="3452168247888906179">"ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਡੀਵਾਈਸ ਨੂੰ ਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="kg_prompt_reason_user_request" msgid="8236951765212462286">"ਡੀਵਾਈਸ ਨੂੰ ਹੱਥੀਂ ਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
     <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="71299470072448533">
-      <item quantity="one">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟੇ ਤੋਂ ਅਨਲੌਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪੈਟਰਨ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
-      <item quantity="other">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟਿਆਂ ਤੋਂ ਅਨਲੌਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪੈਟਰਨ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
+      <item quantity="one">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟੇ ਤੋਂ ਅਣਲਾਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪੈਟਰਨ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
+      <item quantity="other">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟਿਆਂ ਤੋਂ ਅਣਲਾਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪੈਟਰਨ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
     </plurals>
     <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="34586942088144385">
-      <item quantity="one">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟੇ ਤੋਂ ਅਨਲੌਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪਿੰਨ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
-      <item quantity="other">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟਿਆਂ ਤੋਂ ਅਨਲੌਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪਿੰਨ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
+      <item quantity="one">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟੇ ਤੋਂ ਅਣਲਾਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪਿੰਨ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
+      <item quantity="other">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟਿਆਂ ਤੋਂ ਅਣਲਾਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪਿੰਨ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
     </plurals>
     <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="257297696215346527">
-      <item quantity="one">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟੇ ਤੋਂ ਅਨਲੌਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪਾਸਵਰਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ</item>
-      <item quantity="other">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟਿਆਂ ਤੋਂ ਅਨਲੌਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪਾਸਵਰਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ</item>
+      <item quantity="one">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟੇ ਤੋਂ ਅਣਲਾਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪਾਸਵਰਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ</item>
+      <item quantity="other">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟਿਆਂ ਤੋਂ ਅਣਲਾਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪਾਸਵਰਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ</item>
     </plurals>
     <string name="fingerprint_not_recognized" msgid="348813995267914625">"ਪਛਾਣ ਨਹੀਂ ਹੋਈ"</string>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-ta/strings.xml b/packages/SystemUI/res-keyguard/values-ta/strings.xml
index 5f2db2c..9820173 100644
--- a/packages/SystemUI/res-keyguard/values-ta/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ta/strings.xml
@@ -30,7 +30,7 @@
     <string name="keyguard_password_enter_pin_password_code" msgid="7504123374204446086">"திறக்க, பின்னை உள்ளிடவும்"</string>
     <string name="keyguard_password_wrong_pin_code" msgid="6535018036285012028">"தவறான பின் குறியீடு."</string>
     <string name="keyguard_charged" msgid="2222329688813033109">"சார்ஜ் செய்யப்பட்டது"</string>
-    <string name="keyguard_plugged_in" msgid="89308975354638682">"சார்ஜாகிறது"</string>
+    <string name="keyguard_plugged_in" msgid="89308975354638682">"சார்ஜ் ஆகிறது"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="8869226755413795173">"வேகமாகச் சார்ஜாகிறது"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="6637043106038550407">"மெதுவாகச் சார்ஜாகிறது"</string>
     <string name="keyguard_low_battery" msgid="9218432555787624490">"சார்ஜரை இணைக்கவும்."</string>
diff --git a/packages/SystemUI/res/color/qs_detail_progress_track.xml b/packages/SystemUI/res/color/qs_detail_progress_track.xml
index c56382e..d86119f 100644
--- a/packages/SystemUI/res/color/qs_detail_progress_track.xml
+++ b/packages/SystemUI/res/color/qs_detail_progress_track.xml
@@ -16,5 +16,5 @@
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <!-- I really don't want to define this, but the View that uses this asset uses both the
          light and dark accent colors. -->
-    <item android:alpha="0.6" android:drawable="@*android:color/accent_device_default_light" />
+    <item android:alpha="0.6" android:drawable="@*android:color/accent_device_default_dark" />
 </selector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml
index 3eb81f8..b673e4f 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connected.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="64dp"
-    android:height="64dp"
+    android:width="24dp"
+    android:height="24dp"
     android:viewportWidth="24.0"
     android:viewportHeight="24.0"
     android:tint="?android:attr/colorControlNormal" >
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
index dde2db2..2f16516 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
@@ -30,7 +30,8 @@
     <TextView android:id="@+id/user_name"
         android:layout_width="@dimen/car_fullscreen_user_pod_width"
         android:layout_height="wrap_content"
-        android:layout_marginTop="@dimen/car_fullscreen_user_pod_margin_above_text"
+        android:layout_marginTop="@dimen/car_fullscreen_user_pod_margin_name_top"
+        android:layout_marginBottom="@dimen/car_fullscreen_user_pod_margin_name_bottom"
         android:textSize="@dimen/car_fullscreen_user_pod_text_size"
         android:textColor="@color/qs_user_detail_name"
         android:ellipsize="end"
diff --git a/packages/SystemUI/res/layout/car_qs_footer.xml b/packages/SystemUI/res/layout/car_qs_footer.xml
index 96f34fc..044090b 100644
--- a/packages/SystemUI/res/layout/car_qs_footer.xml
+++ b/packages/SystemUI/res/layout/car_qs_footer.xml
@@ -18,23 +18,24 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/qs_footer"
     android:layout_width="match_parent"
-    android:layout_height="@dimen/qs_footer_height"
+    android:layout_height="@dimen/car_qs_footer_height"
     android:baselineAligned="false"
     android:clickable="false"
     android:clipChildren="false"
     android:clipToPadding="false"
-    android:paddingBottom="16dp"
-    android:paddingTop="16dp"
-    android:paddingEnd="32dp"
-    android:paddingStart="32dp"
+    android:paddingBottom="@dimen/car_qs_footer_padding_bottom"
+    android:paddingTop="@dimen/car_qs_footer_padding_top"
+    android:paddingEnd="@dimen/car_qs_footer_padding_end"
+    android:paddingStart="@dimen/car_qs_footer_padding_start"
     android:gravity="center_vertical">
 
     <com.android.systemui.statusbar.phone.MultiUserSwitch
         android:id="@+id/multi_user_switch"
         android:layout_alignParentStart="true"
         android:layout_centerVertical="true"
-        android:layout_width="48dp"
-        android:layout_height="48dp"
+        android:layout_width="@dimen/car_qs_footer_icon_width"
+        android:layout_height="@dimen/car_qs_footer_icon_height"
+        android:layout_marginRight="@dimen/car_qs_footer_user_switch_margin_right"
         android:background="@drawable/ripple_drawable"
         android:focusable="true">
 
@@ -43,15 +44,24 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_gravity="center"
-            android:scaleType="centerInside"/>
+            android:scaleType="fitCenter"/>
     </com.android.systemui.statusbar.phone.MultiUserSwitch>
 
+    <TextView android:id="@+id/user_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="@dimen/car_qs_footer_user_name_text_size"
+        android:textColor="@color/car_qs_footer_user_name_color"
+        android:gravity="start|center_vertical"
+        android:layout_centerVertical="true"
+        android:layout_toEndOf="@id/multi_user_switch" />
+
     <com.android.systemui.statusbar.phone.SettingsButton
         android:id="@+id/settings_button"
         android:layout_alignParentEnd="true"
         android:layout_centerVertical="true"
-        android:layout_width="48dp"
-        android:layout_height="48dp"
+        android:layout_width="@dimen/car_qs_footer_icon_width"
+        android:layout_height="@dimen/car_qs_footer_icon_height"
         android:background="@drawable/ripple_drawable"
         android:contentDescription="@string/accessibility_quick_settings_settings"
         android:scaleType="centerCrop"
diff --git a/packages/SystemUI/res/layout/qs_detail_item.xml b/packages/SystemUI/res/layout/qs_detail_item.xml
index 97e82ff..0844bb4 100644
--- a/packages/SystemUI/res/layout/qs_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_detail_item.xml
@@ -26,7 +26,7 @@
 
     <ImageView
         android:id="@android:id/icon"
-        android:layout_width="@dimen/qs_detail_item_icon_size"
+        android:layout_width="@dimen/qs_detail_item_icon_width"
         android:layout_height="@dimen/qs_detail_item_icon_size"
         android:layout_marginStart="@dimen/qs_detail_item_icon_marginStart"
         android:layout_marginEnd="@dimen/qs_detail_item_icon_marginEnd"
diff --git a/packages/SystemUI/res/layout/volume_zen_footer.xml b/packages/SystemUI/res/layout/volume_zen_footer.xml
index 7ffcb1e..df79c5f 100644
--- a/packages/SystemUI/res/layout/volume_zen_footer.xml
+++ b/packages/SystemUI/res/layout/volume_zen_footer.xml
@@ -25,18 +25,15 @@
         android:id="@+id/zen_embedded_divider"
         android:layout_width="match_parent"
         android:layout_height="1dp"
-        android:layout_marginBottom="12dp"
         android:layout_marginTop="8dp"
         android:background="@color/qs_tile_divider" />
 
-
     <RelativeLayout
         android:id="@+id/zen_introduction"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginStart="16dp"
         android:layout_marginEnd="16dp"
-        android:paddingTop="8dp"
         android:paddingBottom="8dp"
         android:background="@drawable/zen_introduction_message_background"
         android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent.Light">
diff --git a/packages/SystemUI/res/values-bn-land/strings.xml b/packages/SystemUI/res/values-bn-land/strings.xml
index ac873fa..bf53a77 100644
--- a/packages/SystemUI/res/values-bn-land/strings.xml
+++ b/packages/SystemUI/res/values-bn-land/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="toast_rotation_locked" msgid="7609673011431556092">"এখন ভূদৃশ্য সজ্জাতে স্ক্রীণ লক করা হয়েছে৷"</string>
+    <string name="toast_rotation_locked" msgid="7609673011431556092">"এখন ল্যান্ডস্কেপ সজ্জাতে স্ক্রিন লক করা হয়েছে৷"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 0cee705..cd0e9a8 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -342,9 +342,9 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Zatitze horizontala"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Zatitze bertikala"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Zatitze pertsonalizatua"</string>
-    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Banandu pantaila eta ezarri goian"</string>
-    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Banandu pantaila eta ezarri ezkerrean"</string>
-    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Banandu pantaila eta ezarri eskuinean"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Zatitu pantaila eta ezarri goian"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Zatitu pantaila eta ezarri ezkerrean"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Zatitu pantaila eta ezarri eskuinean"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Kargatuta"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 8c384f3..6cab2ec 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -352,7 +352,7 @@
     <string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"Chargée dans <xliff:g id="CHARGING_TIME">%s</xliff:g>"</string>
     <string name="expanded_header_battery_not_charging" msgid="4798147152367049732">"N\'est pas en charge"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Le réseau peut\nêtre surveillé."</string>
-    <string name="description_target_search" msgid="3091587249776033139">"Recherche"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Rechercher"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Faire glisser le doigt vers le haut : <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Faites glisser votre doigt vers la gauche pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="zen_priority_introduction" msgid="1149025108714420281">"Vous ne serez pas dérangé par les sons et les vibrations, sauf pour les alarmes, les rappels, les événements et les appelants que vous sélectionnez. Vous entendrez tout ce que vous choisissez d\'écouter, y compris la musique, les vidéos et les jeux."</string>
diff --git a/packages/SystemUI/res/values-h600dp/dimens_car.xml b/packages/SystemUI/res/values-h600dp/dimens_car.xml
new file mode 100644
index 0000000..c3e62c8
--- /dev/null
+++ b/packages/SystemUI/res/values-h600dp/dimens_car.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2017, 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.
+*/
+-->
+<resources>
+    <dimen name="car_body2_size">32sp</dimen> <!-- B2 -->
+</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 25baf20..0a5c736 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -308,7 +308,7 @@
     <string name="quick_settings_inversion_label" msgid="8790919884718619648">"रंग उलटें"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"रंग सुधार मोड"</string>
     <string name="quick_settings_more_settings" msgid="326112621462813682">"और सेटिंग"</string>
-    <string name="quick_settings_done" msgid="3402999958839153376">"पूर्ण"</string>
+    <string name="quick_settings_done" msgid="3402999958839153376">"हो गया"</string>
     <string name="quick_settings_connected" msgid="1722253542984847487">"कनेक्ट है"</string>
     <string name="quick_settings_connected_battery_level" msgid="4136051440381328892">"कनेक्ट किया गया, बैटरी <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> है"</string>
     <string name="quick_settings_connecting" msgid="47623027419264404">"कनेक्ट हो रहा है..."</string>
diff --git a/packages/SystemUI/res/values-ldrtl/config.xml b/packages/SystemUI/res/values-ldrtl/config.xml
index 40604c1..884c95f 100644
--- a/packages/SystemUI/res/values-ldrtl/config.xml
+++ b/packages/SystemUI/res/values-ldrtl/config.xml
@@ -17,5 +17,5 @@
 <resources>
     <!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows,
          when the PIP menu is shown with settings. -->
-    <string translatable="false" name="pip_settings_bounds">"778 54 1258 324"</string>
+    <string translatable="false" name="pip_settings_bounds">"778 756 1258 1026"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index fe00639..0503b48 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -53,7 +53,7 @@
     <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"वास्तविक कीबोर्ड"</string>
     <string name="usb_device_permission_prompt" msgid="834698001271562057">"USB डिव्हाइसवर प्रवेश करण्यासाठी <xliff:g id="APPLICATION">%1$s</xliff:g> अॅप ला अनुमती द्यायची?"</string>
     <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"अ‍ॅप <xliff:g id="APPLICATION">%1$s</xliff:g> ला USB उपसाधनात प्रवेश करण्‍याची अनुमती द्यायची?"</string>
-    <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"हे USB डीव्हाइस कनेक्ट केलेले असते तेव्हा <xliff:g id="ACTIVITY">%1$s</xliff:g> उघडायचे?"</string>
+    <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"हे USB डिव्हाइस कनेक्ट केलेले असते तेव्हा <xliff:g id="ACTIVITY">%1$s</xliff:g> उघडायचे?"</string>
     <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"हे USB उपसाधन कनेक्ट केलेले असते तेव्हा <xliff:g id="ACTIVITY">%1$s</xliff:g> उघडायचे?"</string>
     <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"इंस्टॉल केलेले अॅप्स या USB उपसाधनासह कार्य करत नाहीत. <xliff:g id="URL">%1$s</xliff:g> येथे या उपसाधनाविषयी अधिक जाणून घ्या"</string>
     <string name="title_usb_accessory" msgid="4966265263465181372">"USB उपसाधन"</string>
@@ -271,7 +271,7 @@
     <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"केवळ अलार्म"</string>
     <string name="quick_settings_dnd_none_label" msgid="5025477807123029478">"संपूर्ण शांतता"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ब्लूटूथ"</string>
-    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ब्लूटूथ (<xliff:g id="NUMBER">%d</xliff:g> डीव्हाइस)"</string>
+    <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ब्लूटूथ (<xliff:g id="NUMBER">%d</xliff:g> डिव्हाइस)"</string>
     <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ब्लूटूथ बंद"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="4910015762433302860">"कोणतेही जोडलेले डिव्हाइसेस उपलब्ध नाहीत"</string>
     <string name="quick_settings_brightness_label" msgid="6968372297018755815">"चमक"</string>
@@ -284,7 +284,7 @@
     <string name="quick_settings_ime_label" msgid="7073463064369468429">"इनपुट पद्धत"</string>
     <string name="quick_settings_location_label" msgid="5011327048748762257">"स्थान"</string>
     <string name="quick_settings_location_off_label" msgid="7464544086507331459">"स्थान बंद"</string>
-    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"मीडिया डीव्हाइस"</string>
+    <string name="quick_settings_media_device_label" msgid="1302906836372603762">"मीडिया डिव्हाइस"</string>
     <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
     <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"फक्त आणीबाणीचे कॉल"</string>
     <string name="quick_settings_settings_label" msgid="5326556592578065401">"सेटिंग्ज"</string>
@@ -300,7 +300,7 @@
     <string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"वाय-फाय नेटवर्क उपलब्‍ध नाहीत"</string>
     <string name="quick_settings_cast_title" msgid="7709016546426454729">"कास्‍ट करा"</string>
     <string name="quick_settings_casting" msgid="6601710681033353316">"कास्ट करत आहे"</string>
-    <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"निनावी डीव्हाइस"</string>
+    <string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"निनावी डिव्हाइस"</string>
     <string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"कास्ट करण्यास तयार"</string>
     <string name="quick_settings_cast_detail_empty_text" msgid="311785821261640623">"कोणतेही डिव्हाइसेस उपलब्ध नाहीत"</string>
     <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"चमक"</string>
@@ -362,8 +362,8 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"खाली कमी तातडीच्या सूचना"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"उघडण्यासाठी पुन्हा टॅप करा"</string>
     <string name="keyguard_unlock" msgid="8043466894212841998">"अनलॉक करण्यासाठी स्वाइप करा"</string>
-    <string name="do_disclosure_generic" msgid="5615898451805157556">"हे डीव्हाइस तुमची संस्था व्यवस्थापित करते"</string>
-    <string name="do_disclosure_with_name" msgid="5640615509915445501">"हे डीव्हाइस <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ने व्यवस्थापित केले आहे"</string>
+    <string name="do_disclosure_generic" msgid="5615898451805157556">"हे डिव्हाइस तुमची संस्था व्यवस्थापित करते"</string>
+    <string name="do_disclosure_with_name" msgid="5640615509915445501">"हे डिव्हाइस <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ने व्यवस्थापित केले आहे"</string>
     <string name="phone_hint" msgid="4872890986869209950">"फोनसाठी चिन्हावरून स्वाइप करा"</string>
     <string name="voice_hint" msgid="8939888732119726665">"व्हॉइस सहाय्यासाठी चिन्हावरून स्वाइप करा"</string>
     <string name="camera_hint" msgid="7939688436797157483">"कॅमेर्‍यासाठी चिन्हावरून स्वाइप करा"</string>
@@ -415,22 +415,22 @@
     <string name="profile_owned_footer" msgid="8021888108553696069">"प्रोफाईलचे परीक्षण केले जाऊ शकते"</string>
     <string name="vpn_footer" msgid="2388611096129106812">"नेटवर्कचे परीक्षण केले जाऊ शकते"</string>
     <string name="branded_vpn_footer" msgid="2168111859226496230">"नेटवर्कचे परीक्षण केले जाऊ शकते"</string>
-    <string name="quick_settings_disclosure_management_monitoring" msgid="6645176135063957394">"आपली संस्था हे डीव्हाइस व्यवस्थापित करते आणि नेटवर्क रहदारीचे परीक्षण करू शकते"</string>
-    <string name="quick_settings_disclosure_named_management_monitoring" msgid="370622174777570853">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> हे डीव्हाइस व्यवस्थापित करते आणि नेटवर्क रहदारीचे परीक्षण करू शकते"</string>
-    <string name="quick_settings_disclosure_management_named_vpn" msgid="1085137869053332307">"डीव्हाइस तुमच्या संस्थेद्वारे व्यवस्थापित केले जाते आणि ते <xliff:g id="VPN_APP">%1$s</xliff:g> शी कनेक्ट केलेले आहे"</string>
-    <string name="quick_settings_disclosure_named_management_named_vpn" msgid="6290456493852584017">"डीव्हाइस <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> द्वारे व्यवस्थापित केले जाते आणि ते <xliff:g id="VPN_APP">%2$s</xliff:g> शी कनेक्ट केलेले आहे"</string>
-    <string name="quick_settings_disclosure_management" msgid="3294967280853150271">"डीव्हाइस तुमच्या संस्थेद्वारे व्यवस्थापित आहे"</string>
-    <string name="quick_settings_disclosure_named_management" msgid="1059403025094542908">"डीव्हाइस <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> द्वारे व्यवस्थापित केले जाते"</string>
-    <string name="quick_settings_disclosure_management_vpns" msgid="3698767349925266482">"डीव्हाइस तुमच्या संस्थेद्वारे व्यवस्थापित केले जाते आणि ते VPN शी कनेक्ट केलेले आहे"</string>
-    <string name="quick_settings_disclosure_named_management_vpns" msgid="7777821385318891527">"डीव्हाइस <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> द्वारे व्यवस्थापित केले जाते आणि ते VPN शी कनेक्ट केलेले आहे"</string>
+    <string name="quick_settings_disclosure_management_monitoring" msgid="6645176135063957394">"आपली संस्था हे डिव्हाइस व्यवस्थापित करते आणि नेटवर्क रहदारीचे परीक्षण करू शकते"</string>
+    <string name="quick_settings_disclosure_named_management_monitoring" msgid="370622174777570853">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> हे डिव्हाइस व्यवस्थापित करते आणि नेटवर्क रहदारीचे परीक्षण करू शकते"</string>
+    <string name="quick_settings_disclosure_management_named_vpn" msgid="1085137869053332307">"डिव्हाइस तुमच्या संस्थेद्वारे व्यवस्थापित केले जाते आणि ते <xliff:g id="VPN_APP">%1$s</xliff:g> शी कनेक्ट केलेले आहे"</string>
+    <string name="quick_settings_disclosure_named_management_named_vpn" msgid="6290456493852584017">"डिव्हाइस <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> द्वारे व्यवस्थापित केले जाते आणि ते <xliff:g id="VPN_APP">%2$s</xliff:g> शी कनेक्ट केलेले आहे"</string>
+    <string name="quick_settings_disclosure_management" msgid="3294967280853150271">"डिव्हाइस तुमच्या संस्थेद्वारे व्यवस्थापित आहे"</string>
+    <string name="quick_settings_disclosure_named_management" msgid="1059403025094542908">"डिव्हाइस <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> द्वारे व्यवस्थापित केले जाते"</string>
+    <string name="quick_settings_disclosure_management_vpns" msgid="3698767349925266482">"डिव्हाइस तुमच्या संस्थेद्वारे व्यवस्थापित केले जाते आणि ते VPN शी कनेक्ट केलेले आहे"</string>
+    <string name="quick_settings_disclosure_named_management_vpns" msgid="7777821385318891527">"डिव्हाइस <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> द्वारे व्यवस्थापित केले जाते आणि ते VPN शी कनेक्ट केलेले आहे"</string>
     <string name="quick_settings_disclosure_managed_profile_monitoring" msgid="5125463987558278215">"आपली संस्था आपल्या कार्य प्रोफाइलमधील नेटवर्क रहदारीचे परीक्षण करू शकते"</string>
     <string name="quick_settings_disclosure_named_managed_profile_monitoring" msgid="8973606847896650284">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> आपल्या कार्य प्रोफाइलमधील नेटवर्क रहदारीचे परीक्षण करू शकते"</string>
     <string name="quick_settings_disclosure_monitoring" msgid="679658227269205728">"नेटवर्कचे परीक्षण केले जाऊ शकते"</string>
-    <string name="quick_settings_disclosure_vpns" msgid="8170318392053156330">"डीव्हाइस VPN शी कनेक्ट केलेले आहे"</string>
+    <string name="quick_settings_disclosure_vpns" msgid="8170318392053156330">"डिव्हाइस VPN शी कनेक्ट केलेले आहे"</string>
     <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="3494535754792751741">"कार्य प्रोफाइल <xliff:g id="VPN_APP">%1$s</xliff:g> शी कनेक्ट केलेले आहे"</string>
     <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="4467456202486569906">"वैयक्तिक प्रोफाइल <xliff:g id="VPN_APP">%1$s</xliff:g> शी कनेक्ट केलेले आहे"</string>
-    <string name="quick_settings_disclosure_named_vpn" msgid="6943724064780847080">"डीव्हाइस <xliff:g id="VPN_APP">%1$s</xliff:g> शी कनेक्ट केलेले आहे"</string>
-    <string name="monitoring_title_device_owned" msgid="1652495295941959815">"डीव्हाइस व्‍यवस्‍थापन"</string>
+    <string name="quick_settings_disclosure_named_vpn" msgid="6943724064780847080">"डिव्हाइस <xliff:g id="VPN_APP">%1$s</xliff:g> शी कनेक्ट केलेले आहे"</string>
+    <string name="monitoring_title_device_owned" msgid="1652495295941959815">"डिव्हाइस व्‍यवस्‍थापन"</string>
     <string name="monitoring_title_profile_owned" msgid="6790109874733501487">"प्रोफाईल परीक्षण"</string>
     <string name="monitoring_title" msgid="169206259253048106">"नेटवर्क परीक्षण"</string>
     <string name="monitoring_subtitle_vpn" msgid="876537538087857300">"VPN"</string>
@@ -439,8 +439,8 @@
     <string name="disable_vpn" msgid="4435534311510272506">"VPN अक्षम करा"</string>
     <string name="disconnect_vpn" msgid="1324915059568548655">"VPN डिस्कनेक्ट करा"</string>
     <string name="monitoring_button_view_policies" msgid="100913612638514424">"धोरणे पहा"</string>
-    <string name="monitoring_description_named_management" msgid="5281789135578986303">"तुमचे डीव्हाइस <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> व्यवस्थापित करते.\n\nतुमचा प्रशासक सेटिंग्ज, कॉर्पोरेट अॅक्सेस, अॅप्स, तुमच्या डीव्हाइस शी संबंधित डेटा आणि तुमच्या डीव्हाइस च्या ठिकाणाची माहिती मॉनिटर करू शकते आणि ती व्यवस्थापित करू शकतो.\n\nआणखी माहितीसाठी, तुमच्या प्रशासकाशी संपर्क साधा."</string>
-    <string name="monitoring_description_management" msgid="4573721970278370790">"तुमचे डीव्हाइस तुमची संस्‍था व्यवस्थापित करते.\n\nतुमचा प्रशासक सेटिंग्ज, कॉर्पोरेट अॅक्सेस, अॅप्स, तुमच्या डीव्हाइस शी संबंधित डेटा आणि तुमच्या डीव्हाइस च्या ठिकाणाची माहिती मॉनिटर करू शकतो आणि ती व्यवस्थापित करू शकतो.\n\nआणखी माहितीसाठी, तुमच्या प्रशासकाशी संपर्क साधा."</string>
+    <string name="monitoring_description_named_management" msgid="5281789135578986303">"तुमचे डिव्हाइस <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> व्यवस्थापित करते.\n\nतुमचा प्रशासक सेटिंग्ज, कॉर्पोरेट अॅक्सेस, अॅप्स, तुमच्या डिव्हाइस शी संबंधित डेटा आणि तुमच्या डिव्हाइस च्या ठिकाणाची माहिती मॉनिटर करू शकते आणि ती व्यवस्थापित करू शकतो.\n\nआणखी माहितीसाठी, तुमच्या प्रशासकाशी संपर्क साधा."</string>
+    <string name="monitoring_description_management" msgid="4573721970278370790">"तुमचे डिव्हाइस तुमची संस्‍था व्यवस्थापित करते.\n\nतुमचा प्रशासक सेटिंग्ज, कॉर्पोरेट अॅक्सेस, अॅप्स, तुमच्या डिव्हाइस शी संबंधित डेटा आणि तुमच्या डिव्हाइस च्या ठिकाणाची माहिती मॉनिटर करू शकतो आणि ती व्यवस्थापित करू शकतो.\n\nआणखी माहितीसाठी, तुमच्या प्रशासकाशी संपर्क साधा."</string>
     <string name="monitoring_description_management_ca_certificate" msgid="5202023784131001751">"आपल्या संस्थेने या डिव्हाइसवर प्रमाणपत्र अधिकार इंस्टॉल केला आहे. आपल्या सुरक्षित नेटवर्क रहदारीचे परीक्षण केले जाऊ शकते किंवा ती सुधारली जाऊ शकते."</string>
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="4683248196789897964">"आपल्या संस्थेने आपल्या कार्य प्रोफाइलवर प्रमाणपत्र अधिकार इंस्टॉल केला आहे. आपल्या सुरक्षित नेटवर्क रहदारीचे परीक्षण केले जाऊ शकते किंवा ती सुधारली जाऊ शकते."</string>
     <string name="monitoring_description_ca_certificate" msgid="7886985418413598352">"या डिव्हाइसवर प्रमाणपत्र अधिकार इंस्टॉल केला आहे. आपल्या सुरक्षित नेटवर्क रहदारीचे परीक्षण केले जाऊ शकते किंवा ती सुधारली जाऊ शकते."</string>
@@ -449,8 +449,8 @@
     <string name="monitoring_description_two_named_vpns" msgid="4198511413729213802">"तुम्‍ही <xliff:g id="VPN_APP_0">%1$s</xliff:g> आणि <xliff:g id="VPN_APP_1">%2$s</xliff:g> शी कनेक्‍ट केले आहे, जे ईमेल, अ‍ॅप्स आणि वेबसाइटसहित आपल्‍या नेटवर्क क्रिया मॉनिटर करू शकते."</string>
     <string name="monitoring_description_managed_profile_named_vpn" msgid="1427905889862420559">"आपले कार्य प्रोफाइल <xliff:g id="VPN_APP">%1$s</xliff:g> शी कनेक्‍ट केले आहे, जे ईमेल, अ‍ॅप्स आणि वेबसाइटसह आपल्‍या नेटवर्क क्रियाकलापाचे परीक्षण करू शकते."</string>
     <string name="monitoring_description_personal_profile_named_vpn" msgid="3133980926929069283">"आपले वैयक्तिक प्रोफाइल <xliff:g id="VPN_APP">%1$s</xliff:g> शी कनेक्‍ट केले आहे, जे ईमेल, अ‍ॅप्स आणि वेबसाइटसह आपल्‍या नेटवर्क क्रियाकलापाचे परीक्षण करू शकते."</string>
-    <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"तुमचे डीव्हाइस <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g> ने व्यवस्थापित केले आहे."</string>
-    <string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"तुमचे डीव्हाइस व्यवस्थापित करण्यासाठी <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> वापरते."</string>
+    <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"तुमचे डिव्हाइस <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g> ने व्यवस्थापित केले आहे."</string>
+    <string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"तुमचे डिव्हाइस व्यवस्थापित करण्यासाठी <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> वापरते."</string>
     <string name="monitoring_description_do_body" msgid="3639594537660975895">"आपला प्रशासक सेटिंग्ज, कॉर्पोरेट प्रवेश, अॅप्स, आपल्या डिव्हाइशी संबंधित डेटा आणि डिव्हाइसच्या स्थान माहितीचे निरीक्षण आणि व्यवस्थापन करू शकतो."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"अधिक जाणून घ्या"</string>
@@ -460,7 +460,7 @@
     <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string>
     <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"विश्वासू क्रेडेंशियल उघडा"</string>
     <string name="monitoring_description_network_logging" msgid="7223505523384076027">"आपल्या प्रशासकाने नेटवर्क लॉगिंग चालू केले आहे, जे आपल्या डिव्हाइसवरील रहदारीचे निरीक्षण करते.\n\nअधिक माहितीसाठी आपल्या प्रशासकाशी संपर्क साधा."</string>
-    <string name="monitoring_description_vpn" msgid="4445150119515393526">"तुम्ही VPN कनेक्शन सेट करण्यासाठी अ‍ॅपला परवानगी दिली.\n\nहा अ‍ॅप ईमेल, अ‍ॅप्स आणि वेबसाइटसह, तुमच्या डीव्हाइस आणि नेटवर्क अॅक्टिव्हिटीचे परीक्षण करू शकतो."</string>
+    <string name="monitoring_description_vpn" msgid="4445150119515393526">"तुम्ही VPN कनेक्शन सेट करण्यासाठी अ‍ॅपला परवानगी दिली.\n\nहा अ‍ॅप ईमेल, अ‍ॅप्स आणि वेबसाइटसह, तुमच्या डिव्हाइस आणि नेटवर्क अॅक्टिव्हिटीचे परीक्षण करू शकतो."</string>
     <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"आपले कार्य प्रोफाइल <xliff:g id="ORGANIZATION">%1$s</xliff:g> द्वारे व्यवस्थापित केले जाते.\n\nआपला प्रशासक ईमेल, अॅप्स आणि वेबसाइटसह आपल्या नेटवर्क अॅक्टिव्हिटीचे निरीक्षण करण्यास सक्षम आहे.\n\nअधिक माहितीसाठी आपल्या प्रशासकाशी संपर्क साधा.\n\nआपण VPN शी देखील कनेक्ट आहात, जे आपल्या नेटवर्क अॅक्टिव्हिटीचे निरीक्षण करू शकते."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="1828472472674709532">"आपण <xliff:g id="APPLICATION">%1$s</xliff:g> शी कनेक्‍ट केले आहे, जे ईमेल, अ‍ॅप्स आणि वेबसाइटसह आपल्‍या नेटवर्क क्रियाकलापाचे परीक्षण करू शकते."</string>
@@ -470,7 +470,7 @@
     <string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"आपले कार्य प्रोफाइल <xliff:g id="ORGANIZATION">%1$s</xliff:g> द्वारे व्यवस्थापित केले जाते. प्रोफाइल <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> शी कनेक्‍ट केले आहे, जे ईमेल, अ‍ॅप्स आणि वेबसाइटसह आपल्‍या कार्य नेटवर्क क्रियाकलापाचे परीक्षण करू शकते.\n\nआपण <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> शीदेखील कनेक्‍ट केले आहे, जे आपल्या वैयक्तिक नेटवर्क क्रियाकलापाचे परीक्षण करू शकते."</string>
     <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"<xliff:g id="USER_NAME">%1$s</xliff:g> साठी अनलॉक केले"</string>
     <string name="keyguard_indication_trust_managed" msgid="8319646760022357585">"<xliff:g id="TRUST_AGENT">%1$s</xliff:g> चालू आहे"</string>
-    <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"तुम्ही मॅन्युअली अनलॉक करेपर्यंत डीव्हाइस लॉक राहील"</string>
+    <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"तुम्ही मॅन्युअली अनलॉक करेपर्यंत डिव्हाइस लॉक राहील"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"सूचना अधिक जलद मिळवा"</string>
     <string name="hidden_notifications_text" msgid="2326409389088668981">"आपण अनलॉक करण्‍यापूर्वी त्यांना पहा"</string>
     <string name="hidden_notifications_cancel" msgid="3690709735122344913">"नाही, नको"</string>
@@ -489,7 +489,7 @@
     <string name="quick_settings_reset_confirmation_button" msgid="2660339101868367515">"लपवा"</string>
     <string name="managed_profile_foreground_toast" msgid="5421487114739245972">"आपण आपले कार्य प्रोफाईल वापरत आहात"</string>
     <string name="stream_voice_call" msgid="4410002696470423714">"कॉल करा"</string>
-    <string name="stream_system" msgid="7493299064422163147">"सिस्टीम"</string>
+    <string name="stream_system" msgid="7493299064422163147">"सिस्टम"</string>
     <string name="stream_ring" msgid="8213049469184048338">"रिंग करा"</string>
     <string name="stream_music" msgid="9086982948697544342">"मीडिया"</string>
     <string name="stream_alarm" msgid="5209444229227197703">"अलार्म"</string>
@@ -510,7 +510,7 @@
     <string name="quick_settings" msgid="10042998191725428">"द्रुत सेटिंग्ज"</string>
     <string name="status_bar" msgid="4877645476959324760">"स्टेटस बार"</string>
     <string name="overview" msgid="4018602013895926956">"अवलोकन"</string>
-    <string name="demo_mode" msgid="2532177350215638026">"सिस्टीम UI डेमो मोड"</string>
+    <string name="demo_mode" msgid="2532177350215638026">"सिस्टम UI डेमो मोड"</string>
     <string name="enable_demo_mode" msgid="4844205668718636518">"डेमो मोड सुरू करा"</string>
     <string name="show_demo_mode" msgid="2018336697782464029">"डेमो मोड दर्शवा"</string>
     <string name="status_bar_ethernet" msgid="5044290963549500128">"इथरनेट"</string>
@@ -614,7 +614,7 @@
     <string name="keyboard_key_insert" msgid="8530501581636082614">"घाला"</string>
     <string name="keyboard_key_num_lock" msgid="5052537581246772117">"Num Lock"</string>
     <string name="keyboard_key_numpad_template" msgid="8729216555174634026">"Numpad <xliff:g id="NAME">%1$s</xliff:g>"</string>
-    <string name="keyboard_shortcut_group_system" msgid="6472647649616541064">"सिस्टीम"</string>
+    <string name="keyboard_shortcut_group_system" msgid="6472647649616541064">"सिस्टम"</string>
     <string name="keyboard_shortcut_group_system_home" msgid="3054369431319891965">"होम"</string>
     <string name="keyboard_shortcut_group_system_recents" msgid="3154851905021926744">"अलीकडील"</string>
     <string name="keyboard_shortcut_group_system_back" msgid="2207004531216446378">"परत"</string>
diff --git a/packages/SystemUI/res/values-ne/strings_car.xml b/packages/SystemUI/res/values-ne/strings_car.xml
index d81a488..d4d7d0b 100644
--- a/packages/SystemUI/res/values-ne/strings_car.xml
+++ b/packages/SystemUI/res/values-ne/strings_car.xml
@@ -20,5 +20,5 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="unknown_user_label" msgid="4323896111737677955">"अज्ञात"</string>
-    <string name="start_driving" msgid="864023351402918991">"ड्राइभिङ सुरू गर्नुहोस्"</string>
+    <string name="start_driving" msgid="864023351402918991">"ड्राइभिङ सुरु गर्नुहोस्"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index e94e95b..166e0cb 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -24,7 +24,7 @@
     <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"ਸੂਚੀ ਵਿੱਚੋਂ ਹਟਾਓ"</string>
     <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"ਐਪ ਜਾਣਕਾਰੀ"</string>
     <string name="status_bar_no_recent_apps" msgid="7374907845131203189">"ਤੁਹਾਡੀਆਂ ਹਾਲੀਆ ਸਕ੍ਰੀਨਾਂ ਇੱਥੇ ਪ੍ਰਗਟ ਹੋਣਗੀਆਂ"</string>
-    <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"ਹਾਲੀਆ ਐਪਾਂ ਰੱਦ ਕਰੋ"</string>
+    <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"ਹਾਲੀਆ ਐਪਾਂ ਨੂੰ ਖਾਰਜ ਕਰੋ"</string>
     <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
       <item quantity="one">ਰੂਪ-ਰੇਖਾ ਵਿੱਚ %d ਸਕ੍ਰੀਨਾਂ</item>
       <item quantity="other">ਰੂਪ-ਰੇਖਾ ਵਿੱਚ %d ਸਕ੍ਰੀਨਾਂ</item>
@@ -67,19 +67,19 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"The user currently signed in to this device can\'t turn on USB debugging. To use this feature, switch to the primary user."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"ਸਕ੍ਰੀਨ ਭਰਨ ਲਈ ਜ਼ੂਮ ਕਰੋ"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"ਸਕ੍ਰੀਨ ਭਰਨ ਲਈ ਸਟ੍ਰੈਚ ਕਰੋ"</string>
-    <string name="screenshot_saving_ticker" msgid="7403652894056693515">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
-    <string name="screenshot_saving_title" msgid="8242282144535555697">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਸੁਰੱਖਿਅਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ।"</string>
+    <string name="screenshot_saving_ticker" msgid="7403652894056693515">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
+    <string name="screenshot_saving_title" msgid="8242282144535555697">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
+    <string name="screenshot_saving_text" msgid="2419718443411738818">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ।"</string>
     <string name="screenshot_saved_title" msgid="6461865960961414961">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਕੈਪਚਰ ਕੀਤਾ।"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"ਆਪਣਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਵੇਖਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"ਸਕ੍ਰੀਨਸ਼ੌਟ ਕੈਪਚਰ ਨਹੀਂ ਕਰ ਸਕਿਆ।"</string>
+    <string name="screenshot_saved_text" msgid="2685605830386712477">"ਆਪਣਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇਖਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+    <string name="screenshot_failed_title" msgid="705781116746922771">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਕੈਪਚਰ ਨਹੀਂ ਕਰ ਸਕਿਆ।"</string>
     <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਕਰਨ ਦੌਰਾਨ ਸਮੱਸਿਆ ਆਈ।"</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ਸੀਮਿਤ ਸਟੋਰੇਜ ਥਾਂ ਦੇ ਕਾਰਨ ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਸਕਦਾ।"</string>
+    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ਸਟੋਰੇਜ ਦੀ ਸੀਮਿਤ ਜਗ੍ਹਾ ਹੋਣ ਕਾਰਨ ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਸਕਦਾ।"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ਐਪ ਜਾਂ ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲੈਣ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੱਤੀ ਗਈ ਹੈ"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ ਚੋਣਾਂ"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ਇੱਕ ਮੀਡੀਆ ਪਲੇਅਰ (MTP) ਦੇ ਤੌਰ ਤੇ ਮਾਊਂਟ ਕਰੋ"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"ਇੱਕ ਕੈਮਰੇ (PTP) ਦੇ ਤੌਰ ਤੇ ਮਾਊਂਟ ਕਰੋ"</string>
-    <string name="installer_cd_button_title" msgid="2312667578562201583">"Mac ਲਈ Android ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ ਐਪ ਇੰਸਟੌਲ ਕਰੋ"</string>
+    <string name="installer_cd_button_title" msgid="2312667578562201583">"Mac ਲਈ Android ਫ਼ਾਈਲ ਟ੍ਰਾਂਸਫਰ ਐਪ ਸਥਾਪਤ ਕਰੋ"</string>
     <string name="accessibility_back" msgid="567011538994429120">"ਪਿੱਛੇ"</string>
     <string name="accessibility_home" msgid="8217216074895377641">"ਘਰ"</string>
     <string name="accessibility_menu" msgid="316839303324695949">"ਮੀਨੂ"</string>
@@ -87,13 +87,13 @@
     <string name="accessibility_recent" msgid="5208608566793607626">"ਰੂਪ-ਰੇਖਾ"</string>
     <string name="accessibility_search_light" msgid="1103867596330271848">"ਖੋਜੋ"</string>
     <string name="accessibility_camera_button" msgid="8064671582820358152">"ਕੈਮਰਾ"</string>
-    <string name="accessibility_phone_button" msgid="6738112589538563574">"ਫੋਨ"</string>
+    <string name="accessibility_phone_button" msgid="6738112589538563574">"ਫ਼ੋਨ ਕਰੋ"</string>
     <string name="accessibility_voice_assist_button" msgid="487611083884852965">"ਅਵਾਜ਼ੀ ਸਹਾਇਕ"</string>
-    <string name="accessibility_unlock_button" msgid="128158454631118828">"ਅਨਲੌਕ ਕਰੋ"</string>
+    <string name="accessibility_unlock_button" msgid="128158454631118828">"ਅਣਲਾਕ ਕਰੋ"</string>
     <string name="accessibility_waiting_for_fingerprint" msgid="4808860050517462885">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦੀ ਉਡੀਕ ਹੋ ਰਹੀ ਹੈ"</string>
-    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"ਆਪਣਾ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੇ ਬਿਨਾਂ ਅਨਲੌਕ ਕਰੋ"</string>
-    <string name="unlock_label" msgid="8779712358041029439">"ਅਨਲੌਕ ਕਰੋ"</string>
-    <string name="phone_label" msgid="2320074140205331708">"ਫੋਨ ਖੋਲ੍ਹੋ"</string>
+    <string name="accessibility_unlock_without_fingerprint" msgid="7541705575183694446">"ਆਪਣਾ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੇ ਬਿਨਾਂ ਅਣਲਾਕ ਕਰੋ"</string>
+    <string name="unlock_label" msgid="8779712358041029439">"ਅਣਲਾਕ ਕਰੋ"</string>
+    <string name="phone_label" msgid="2320074140205331708">"ਫ਼ੋਨ ਖੋਲ੍ਹੋ"</string>
     <string name="voice_assist_label" msgid="3956854378310019854">"ਅਵਾਜ਼ੀ ਸਹਾਇਕ ਖੋਲ੍ਹੋ"</string>
     <string name="camera_label" msgid="7261107956054836961">"ਕੈਮਰਾ ਖੋਲ੍ਹੋ"</string>
     <string name="recents_caption_resize" msgid="3517056471774958200">"ਨਵਾਂ ਕੰਮ ਲੇਆਉਟ ਚੁਣੋ"</string>
@@ -107,11 +107,11 @@
     <string name="accessibility_battery_two_bars" msgid="8500650438735009973">"ਬੈਟਰੀ ਦੋ ਬਾਰਸ।"</string>
     <string name="accessibility_battery_three_bars" msgid="2302983330865040446">"ਬੈਟਰੀ ਤਿੰਨ ਬਾਰਸ।"</string>
     <string name="accessibility_battery_full" msgid="8909122401720158582">"ਬੈਟਰੀ ਪੂਰੀ।"</string>
-    <string name="accessibility_no_phone" msgid="4894708937052611281">"ਕੋਈ ਫੋਨ ਨਹੀਂ।"</string>
-    <string name="accessibility_phone_one_bar" msgid="687699278132664115">"ਫੋਨ ਇੱਕ ਬਾਰ।"</string>
-    <string name="accessibility_phone_two_bars" msgid="8384905382804815201">"ਫੋਨ ਦੋ ਬਾਰਸ।"</string>
-    <string name="accessibility_phone_three_bars" msgid="8521904843919971885">"ਫੋਨ ਤਿੰਨ ਬਾਰਸ।"</string>
-    <string name="accessibility_phone_signal_full" msgid="6471834868580757898">"ਫੋਨ ਸਿਗਨਲ ਪੂਰਾ।"</string>
+    <string name="accessibility_no_phone" msgid="4894708937052611281">"ਕੋਈ ਫ਼ੋਨ ਨਹੀਂ।"</string>
+    <string name="accessibility_phone_one_bar" msgid="687699278132664115">"ਫ਼ੋਨ ਇੱਕ ਬਾਰ।"</string>
+    <string name="accessibility_phone_two_bars" msgid="8384905382804815201">"ਫ਼ੋਨ ਦੋ ਬਾਰਸ।"</string>
+    <string name="accessibility_phone_three_bars" msgid="8521904843919971885">"ਫ਼ੋਨ ਤਿੰਨ ਬਾਰਸ।"</string>
+    <string name="accessibility_phone_signal_full" msgid="6471834868580757898">"ਫ਼ੋਨ ਸਿਗਨਲ ਪੂਰਾ।"</string>
     <string name="accessibility_no_data" msgid="4791966295096867555">"ਕੋਈ  ਡਾਟਾ  ਨਹੀਂ।"</string>
     <string name="accessibility_data_one_bar" msgid="1415625833238273628">" ਡਾਟਾ  ਇੱਕ ਬਾਰ।"</string>
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">" ਡਾਟਾ  ਦੋ ਬਾਰਸ।"</string>
@@ -175,7 +175,7 @@
     <!-- no translation found for accessibility_casting (6887382141726543668) -->
     <skip />
     <string name="accessibility_work_mode" msgid="2478631941714607225">"ਕੰਮ ਮੋਡ"</string>
-    <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ਨੂੰ ਰੱਦ ਕਰੋ।"</string>
+    <string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g> ਨੂੰ ਖਾਰਜ ਕਰੋ।"</string>
     <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ਰੱਦ ਕੀਤਾ।"</string>
     <string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"ਸਾਰੀਆਂ ਹਾਲੀਆ ਐਪਲੀਕੇਸ਼ਨਾਂ ਰੱਦ ਕੀਤੀਆਂ।"</string>
     <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> ਐਪਲੀਕੇਸ਼ਨਾਂ ਜਾਣਕਾਰੀ ਖੋਲ੍ਹੋ।"</string>
@@ -339,7 +339,7 @@
     <string name="recents_drag_hint_message" msgid="2649739267073203985">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਇੱਥੇ ਘਸੀਟੋ"</string>
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ਹੌਰੀਜ਼ੌਂਟਲ ਸਪਲਿਟ"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ਵਰਟੀਕਲ ਸਪਲਿਟ"</string>
-    <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ਕਸਟਮ ਸਪਲਿਟ"</string>
+    <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"ਵਿਉਂਂਤੀ ਸਪਲਿਟ"</string>
     <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"ਸਕ੍ਰੀਨ ਨੂੰ ਉੱਪਰ ਵੱਲ ਵਿਭਾਜਿਤ ਕਰੋ"</string>
     <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"ਸਕ੍ਰੀਨ ਨੂੰ ਖੱਬੇ ਪਾਸੇ ਵਿਭਾਜਿਤ ਕਰੋ"</string>
     <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"ਸਕ੍ਰੀਨ ਨੂੰ ਸੱਜੇ ਪਾਸੇ ਵਿਭਾਜਿਤ ਕਰੋ"</string>
@@ -355,18 +355,18 @@
     <string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ਤੱਕ ਖੱਬੇ ਪਾਸੇ ਸਲਾਈਡ ਕਰੋ।"</string>
     <string name="zen_priority_introduction" msgid="1149025108714420281">"ਧੁਨੀਆਂ ਅਤੇ ਥਰਥਰਾਹਟਾਂ ਤੁਹਾਨੂੰ ਪਰੇਸ਼ਾਨ ਨਹੀਂ ਕਰਨਗੀਆਂ, ਸਿਵਾਏ ਅਲਾਰਮਾਂ, ਯਾਦ-ਦਹਾਨੀਆਂ, ਵਰਤਾਰਿਆਂ, ਅਤੇ ਤੁਹਾਡੇ ਵੱਲੋਂ ਨਿਰਧਾਰਤ ਕੀਤੇ ਕਾਲਰਾਂ ਦੀ ਸੂਰਤ ਵਿੱਚ। ਤੁਸੀਂ ਅਜੇ ਵੀ ਸੰਗੀਤ, ਵੀਡੀਓ ਅਤੇ ਗੇਮਾਂ ਸਮੇਤ ਆਪਣੀ ਚੋਣ ਅਨੁਸਾਰ ਕੁਝ ਵੀ ਸੁਣ ਸਕਦੇ ਹੋ।"</string>
     <string name="zen_alarms_introduction" msgid="4934328096749380201">"ਧੁਨੀਆਂ ਅਤੇ ਥਰਥਰਾਹਟਾਂ ਤੁਹਾਨੂੰ ਪਰੇਸ਼ਾਨ ਨਹੀਂ ਕਰਨਗੀਆਂ, ਸਿਵਾਏ ਅਲਾਰਮਾਂ ਦੀ ਸੂਰਤ ਵਿੱਚ। ਤੁਸੀਂ ਅਜੇ ਵੀ ਸੰਗੀਤ, ਵੀਡੀਓ ਅਤੇ ਗੇਮਾਂ ਸਮੇਤ ਆਪਣੀ ਚੋਣ ਅਨੁਸਾਰ ਕੁਝ ਵੀ ਸੁਣ ਸਕਦੇ ਹੋ।"</string>
-    <string name="zen_priority_customize_button" msgid="7948043278226955063">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ ਕਰੋ"</string>
-    <string name="zen_silence_introduction_voice" msgid="3948778066295728085">"ਇਹ ਅਲਾਰਮ, ਸੰਗੀਤ, ਵੀਡੀਓ, ਅਤੇ ਗੇਮਾਂ ਸਮੇਤ, ਸਾਰੀਆਂ ਧੁਨੀਆਂ ਅਤੇ ਥਰਥਰਾਹਟਾਂ ਨੂੰ ਬਲੌਕ ਕਰਦਾ ਹੈ। ਤੁਸੀਂ ਅਜੇ ਵੀ ਫ਼ੋਨ ਕਾਲ ਕਰਨ ਦੇ ਯੋਗ ਹੋਵੋਂਗੇ।"</string>
+    <string name="zen_priority_customize_button" msgid="7948043278226955063">"ਵਿਉਂਤਬੱਧ ਕਰੋ"</string>
+    <string name="zen_silence_introduction_voice" msgid="3948778066295728085">"ਇਹ ਅਲਾਰਮ, ਸੰਗੀਤ, ਵੀਡੀਓ, ਅਤੇ ਗੇਮਾਂ ਸਮੇਤ, ਸਾਰੀਆਂ ਧੁਨੀਆਂ ਅਤੇ ਥਰਥਰਾਹਟਾਂ ਨੂੰ ਬਲਾਕ ਕਰਦਾ ਹੈ। ਤੁਸੀਂ ਅਜੇ ਵੀ ਫ਼ੋਨ ਕਾਲ ਕਰਨ ਦੇ ਯੋਗ ਹੋਵੋਂਗੇ।"</string>
     <string name="zen_silence_introduction" msgid="3137882381093271568">"ਇਹ ਅਲਾਰਮ, ਸੰਗੀਤ, ਵੀਡੀਓਜ਼, ਅਤੇ ਗੇਮਸ ਸਮੇਤ, ਸਾਰੀਆਂ ਧੁਨੀਆਂ ਅਤੇ ਵਾਇਬ੍ਰੇਸ਼ਨ ਨੂੰ ਬਲੌਕ ਕਰਦਾ ਹੈ।"</string>
     <string name="keyguard_more_overflow_text" msgid="9195222469041601365">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
     <string name="speed_bump_explanation" msgid="1288875699658819755">"ਹੇਠਾਂ ਘੱਟ ਲਾਜ਼ਮੀ ਸੂਚਨਾਵਾਂ"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"ਖੋਲ੍ਹਣ ਲਈ ਦੁਬਾਰਾ ਟੈਪ ਕਰੋ"</string>
-    <string name="keyguard_unlock" msgid="8043466894212841998">"ਅਨਲੌਕ ਕਰਨ ਲਈ ਉੱਪਰ ਸਵਾਈਪ ਕਰੋ।"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"ਅਣਲਾਕ ਕਰਨ ਲਈ ਉੱਪਰ ਸਵਾਈਪ ਕਰੋ।"</string>
     <string name="do_disclosure_generic" msgid="5615898451805157556">"ਇਸ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਬੰਧਨ ਤੁਹਾਡੇ ਸੰਗਠਨ ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ"</string>
     <string name="do_disclosure_with_name" msgid="5640615509915445501">"ਇਹ ਡੀਵਾਈਸ <xliff:g id="ORGANIZATION_NAME">%s</xliff:g> ਵੱਲੋਂ ਪ੍ਰਬੰਧਿਤ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
-    <string name="phone_hint" msgid="4872890986869209950">"ਫ਼ੋਨ ਲਈ ਆਈਕਨ ਤੋਂ ਸਵਾਈਪ ਕਰੋ"</string>
-    <string name="voice_hint" msgid="8939888732119726665">"ਅਵਾਜ਼ੀ ਸਹਾਇਕ ਲਈ ਆਈਕਨ ਤੋਂ ਸਵਾਈਪ ਕਰੋ"</string>
-    <string name="camera_hint" msgid="7939688436797157483">"ਕੈਮਰੇ ਲਈ ਆਈਕਨ ਤੋਂ ਸਵਾਈਪ ਕਰੋ"</string>
+    <string name="phone_hint" msgid="4872890986869209950">"ਫ਼ੋਨ ਲਈ ਪ੍ਰਤੀਕ ਤੋਂ ਸਵਾਈਪ ਕਰੋ"</string>
+    <string name="voice_hint" msgid="8939888732119726665">"ਅਵਾਜ਼ੀ ਸਹਾਇਕ ਲਈ ਪ੍ਰਤੀਕ ਤੋਂ ਸਵਾਈਪ ਕਰੋ"</string>
+    <string name="camera_hint" msgid="7939688436797157483">"ਕੈਮਰੇ ਲਈ ਪ੍ਰਤੀਕ ਤੋਂ ਸਵਾਈਪ ਕਰੋ"</string>
     <string name="interruption_level_none_with_warning" msgid="5114872171614161084">"ਪੂਰਾ ਸ਼ਾਂਤ। ਇਹ ਸਕ੍ਰੀਨ ਰੀਡਰਾਂ ਨੂੰ ਵੀ ਸ਼ਾਂਤ ਕਰ ਦੇਵੇਗਾ।"</string>
     <string name="interruption_level_none" msgid="6000083681244492992">"ਪੂਰਾ ਸ਼ਾਂਤ"</string>
     <string name="interruption_level_priority" msgid="6426766465363855505">"ਕੇਵਲ ਤਰਜੀਹੀ"</string>
@@ -438,7 +438,7 @@
     <string name="monitoring_subtitle_ca_certificate" msgid="3874151893894355988">"CA ਪ੍ਰਮਾਣ-ਪੱਤਰ"</string>
     <string name="disable_vpn" msgid="4435534311510272506">"VPN ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਓ"</string>
     <string name="disconnect_vpn" msgid="1324915059568548655">"VPN ਨੂੰ ਡਿਸਕਨੈਕਟ ਕਰੋ"</string>
-    <string name="monitoring_button_view_policies" msgid="100913612638514424">"ਨੀਤੀਆਂ ਵੇਖੋ"</string>
+    <string name="monitoring_button_view_policies" msgid="100913612638514424">"ਨੀਤੀਆਂ ਦੇਖੋ"</string>
     <string name="monitoring_description_named_management" msgid="5281789135578986303">"ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਬੰਧਨ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।\n\nਤੁਹਾਡਾ ਪ੍ਰਸ਼ਾਸਕ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨਾਲ ਸਬੰਧਿਤ ਸੈਟਿੰਗਾਂ, ਕਾਰਪੋਰੇਟ ਪਹੁੰਚ, ਐਪਾਂ, ਡਾਟਾ ਅਤੇ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਦੀ ਟਿਕਾਣਾ ਜਾਣਕਾਰੀ ਦੀ ਨਿਗਰਾਨੀ ਅਤੇ ਉਹਨਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰ ਸਕਦਾ ਹੈ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
     <string name="monitoring_description_management" msgid="4573721970278370790">"ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦਾ ਪ੍ਰਬੰਧਨ ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।\n\nਤੁਹਾਡਾ ਪ੍ਰਸ਼ਾਸਕ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨਾਲ ਸਬੰਧਿਤ ਸੈਟਿੰਗਾਂ, ਕਾਰਪੋਰੇਟ ਪਹੁੰਚ, ਐਪਾਂ, ਡਾਟਾ ਅਤੇ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀ ਟਿਕਾਣਾ ਜਾਣਕਾਰੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦਾ ਹੈ ਅਤੇ ਉਹਨਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰ ਸਕਦਾ ਹੈ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
     <string name="monitoring_description_management_ca_certificate" msgid="5202023784131001751">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਇੱਕ ਪ੍ਰਮਾਣ-ਪੱਤਰ ਅਥਾਰਟੀ ਸਥਾਪਤ ਕੀਤੀ ਗਈ ਹੈ। ਤੁਹਾਡੇ ਸੁਰੱਖਿਅਤ ਨੈੱਟਵਰਕ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ ਜਾਂ ਉਸਨੂੰ ਸੋਧਿਆ ਜਾ ਸਕਦਾ ਹੈ।"</string>
@@ -459,8 +459,8 @@
     <string name="monitoring_description_vpn_settings" msgid="6434859242636063861">"VPN ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹੋ"</string>
     <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string>
     <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"ਭਰੋਸੇਯੋਗ ਕ੍ਰੀਡੈਂਸ਼ੀਅਲ ਖੋਲ੍ਹੋ"</string>
-    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਨੇ ਨੈੱਟਵਰਕ ਲੌਗਿੰਗ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਹੋਇਆ ਹੈ, ਜੋ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰਦਾ ਹੈ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string>
-    <string name="monitoring_description_vpn" msgid="4445150119515393526">"ਤੁਸੀਂ ਕਿਸੇ ਐਪ ਨੂੰ ਇੱਕ VPN ਕਨੈਕਸ਼ਨ ਸੈੱਟ ਅੱਪ ਕਰਨ ਦੀ ਅਨੁਮਤੀ ਦਿੱਤੀ ਹੈ।\n\nਇਹ ਐਪ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਅਤੇ ਨੈੱਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰ ਸਕਦੀ ਹੈ, ਈਮੇਲਾਂ, ਐਪਾਂ ਅਤੇ ਸੁਰੱਖਿਅਤ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ।"</string>
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਨੇ ਨੈੱਟਵਰਕ ਲੌਗਿੰਗ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਹੋਇਆ ਹੈ, ਜੋ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰਦਾ ਹੈ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
+    <string name="monitoring_description_vpn" msgid="4445150119515393526">"ਤੁਸੀਂ ਕਿਸੇ ਐਪ ਨੂੰ ਇੱਕ VPN ਕਨੈਕਸ਼ਨ ਸੈੱਟ ਅੱਪ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿੱਤੀ ਹੈ।\n\nਇਹ ਐਪ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਅਤੇ ਨੈੱਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰ ਸਕਦੀ ਹੈ, ਈਮੇਲਾਂ, ਐਪਾਂ ਅਤੇ ਸੁਰੱਖਿਅਤ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ।"</string>
     <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"ਤੁਹਾਡੇ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਦਾ ਪ੍ਰਬੰਧਨ <xliff:g id="ORGANIZATION">%1$s</xliff:g> ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।\n\nਤੁਹਾਡਾ ਪ੍ਰਸ਼ਾਸਕ ਈਮੇਲ, ਐਪਾਂ, ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰਨ ਦੇ ਸਮਰੱਥ ਹੈ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।\n\nਤੁਸੀਂ ਇੱਕ VPN ਨਾਲ ਵੀ ਕਨੈਕਟ ਹੋਂ, ਜੋ ਤੁਹਾਡੀ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦਾ ਹੈ।"</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="1828472472674709532">"ਤੁਸੀਂ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੋ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਨੈਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।"</string>
@@ -470,9 +470,9 @@
     <string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"ਤੁਹਾਡੇ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਦਾ ਪ੍ਰਬੰਧਨ <xliff:g id="ORGANIZATION">%1$s</xliff:g> ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਪ੍ਰੋਫਾਈਲ <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ ਹੈ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ, ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਕਾਰਜ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।\n\nਤੁਸੀਂ <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> ਨਾਲ ਵੀ ਕਨੈਕਟ ਹੋਂ, ਜੋ ਤੁਹਾਡੀ ਨਿੱਜੀ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।"</string>
     <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"<xliff:g id="USER_NAME">%1$s</xliff:g> ਲਈ ਅਨਲੌਕ ਕੀਤੀ ਗਈ"</string>
     <string name="keyguard_indication_trust_managed" msgid="8319646760022357585">"<xliff:g id="TRUST_AGENT">%1$s</xliff:g> ਚੱਲ ਰਿਹਾ ਹੈ"</string>
-    <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"ਡੀਵਾਈਸ ਲੌਕ ਰਹੇਗਾ ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਮੈਨੂਅਲੀ ਅਨਲੌਕ ਨਹੀਂ ਕਰਦੇ"</string>
+    <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"ਡੀਵਾਈਸ ਲਾਕ ਰਹੇਗਾ ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਮੈਨੂਅਲੀ ਅਣਲਾਕ ਨਹੀਂ ਕਰਦੇ"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"ਤੇਜ਼ੀ ਨਾਲ ਸੂਚਨਾਵਾਂ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
-    <string name="hidden_notifications_text" msgid="2326409389088668981">"ਅਨਲੌਕ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਉਹਨਾਂ ਨੂੰ ਦੇਖੋ"</string>
+    <string name="hidden_notifications_text" msgid="2326409389088668981">"ਅਣਲਾਕ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਉਹਨਾਂ ਨੂੰ ਦੇਖੋ"</string>
     <string name="hidden_notifications_cancel" msgid="3690709735122344913">"ਨਹੀਂ ਧੰਨਵਾਦ"</string>
     <string name="hidden_notifications_setup" msgid="41079514801976810">"ਸਥਾਪਤ ਕਰੋ"</string>
     <string name="zen_mode_and_condition" msgid="4462471036429759903">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
@@ -502,13 +502,13 @@
     <string name="volume_stream_content_description_mute" msgid="3625049841390467354">"%1$s। ਮਿਊਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ। ਪਹੁੰਚਯੋਗਤਾ ਸੇਵਾਵਾਂ ਮਿਊਟ ਹੋ ਸਕਦੀਆਂ ਹਨ।"</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="6427727603978431301">"%1$s। ਥਰਥਰਾਹਟ \'ਤੇ ਸੈੱਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
     <string name="volume_stream_content_description_mute_a11y" msgid="8995013018414535494">"%1$s। ਮਿਊਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
-    <string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s ਵੌਲਿਊਮ ਕੰਟਰੋਲ ਦਿਖਾਏ ਗਏ ਹਨ। ਖਾਰਜ ਕਰਨ ਲਈ ਉੱਪਰ ਸਵਾਈਪ ਕਰੋ।"</string>
+    <string name="volume_dialog_accessibility_shown_message" msgid="1834631467074259998">"%s ਅਵਾਜ਼ ਕੰਟਰੋਲ ਦਿਖਾਏ ਗਏ ਹਨ। ਖਾਰਜ ਕਰਨ ਲਈ ਉੱਪਰ ਸਵਾਈਪ ਕਰੋ।"</string>
     <string name="volume_dialog_accessibility_dismissed_message" msgid="51543526013711399">"ਵੌਲਿਊਮ ਕੰਟਰੋਲ ਲੁਕਾਏ ਗਏ ਹਨ"</string>
     <string name="system_ui_tuner" msgid="708224127392452018">"System UI ਟਿਊਨਰ"</string>
     <string name="show_battery_percentage" msgid="5444136600512968798">"ਜੋਡ਼ੀ ਗਈ ਬੈਟਰੀ ਪ੍ਰਤਿਸ਼ਤਤਾ ਦਿਖਾਓ"</string>
-    <string name="show_battery_percentage_summary" msgid="3215025775576786037">"ਜਦੋਂ ਚਾਰਜ ਨਾ ਹੋ ਰਹੀ ਹੋਵੇ ਤਾਂ ਸਥਿਤੀ ਬਾਰ ਦੇ ਅੰਦਰ ਬੈਟਰੀ ਪੱਧਰ ਪ੍ਰਤਿਸ਼ਤਤਾ ਦਿਖਾਓ"</string>
+    <string name="show_battery_percentage_summary" msgid="3215025775576786037">"ਜਦੋਂ ਚਾਰਜ ਨਾ ਹੋ ਰਹੀ ਹੋਵੇ ਤਾਂ ਸਥਿਤੀ ਪੱਟੀ ਪ੍ਰਤੀਕ ਦੇ ਅੰਦਰ ਬੈਟਰੀ ਪੱਧਰ ਪ੍ਰਤਿਸ਼ਤਤਾ ਦਿਖਾਓ"</string>
     <string name="quick_settings" msgid="10042998191725428">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ"</string>
-    <string name="status_bar" msgid="4877645476959324760">"ਸਥਿਤੀ ਬਾਰ"</string>
+    <string name="status_bar" msgid="4877645476959324760">"ਸਥਿਤੀ ਪੱਟੀ"</string>
     <string name="overview" msgid="4018602013895926956">"ਰੂਪ-ਰੇਖਾ"</string>
     <string name="demo_mode" msgid="2532177350215638026">"ਸਿਸਟਮ UI ਡੈਮੋ ਮੋਡ"</string>
     <string name="enable_demo_mode" msgid="4844205668718636518">"ਡੈਮੋ ਮੋਡ ਚਾਲੂ ਕਰੋ"</string>
@@ -517,7 +517,7 @@
     <string name="status_bar_alarm" msgid="8536256753575881818">"ਅਲਾਰਮ"</string>
     <string name="status_bar_work" msgid="6022553324802866373">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string>
     <string name="status_bar_airplane" msgid="7057575501472249002">"ਜਹਾਜ਼ ਮੋਡ"</string>
-    <string name="add_tile" msgid="2995389510240786221">"ਟਾਇਲ ਜੋੜੋ"</string>
+    <string name="add_tile" msgid="2995389510240786221">"ਟਾਇਲ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="broadcast_tile" msgid="3894036511763289383">"ਪ੍ਰਸਾਰਨ ਟਾਇਲ"</string>
     <string name="zen_alarm_warning_indef" msgid="3482966345578319605">"ਤੁਸੀਂ <xliff:g id="WHEN">%1$s</xliff:g> ਵਜੇ ਆਪਣਾ ਅਗਲਾ ਅਲਾਰਮ ਨਹੀਂ ਸੁਣੋਗੇ ਜਦੋਂ ਤੱਕ ਉਸਤੋਂ ਪਹਿਲਾਂ ਤੁਸੀਂ ਇਸਨੂੰ ਬੰਦ ਨਹੀਂ ਕਰਦੇ"</string>
     <string name="zen_alarm_warning" msgid="444533119582244293">"ਤੁਸੀਂ <xliff:g id="WHEN">%1$s</xliff:g> ਵਜੇ ਆਪਣਾ ਅਗਲਾ ਅਲਾਰਮ ਨਹੀਂ ਸੁਣੋਗੇ"</string>
@@ -535,7 +535,7 @@
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"ਕੀ ਸੈਟਿੰਗਾਂ ਤੋਂ ਸਿਸਟਮ UI ਟਿਊਨਰ ਨੂੰ ਹਟਾਉਣਾ ਹੈ ਅਤੇ ਇਸਦੀਆਂ ਸਾਰੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਵਰਤੋਂ ਕਰਨ ਤੋਂ ਰੋਕਣਾ ਹੈ?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"ਐਪਲੀਕੇਸ਼ਨ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਤੇ ਸਥਾਪਤ ਨਹੀਂ ਕੀਤੀ ਗਈ ਹੈ"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"ਘੜੀ ਸਕਿੰਟ ਦਿਖਾਓ"</string>
-    <string name="clock_seconds_desc" msgid="6282693067130470675">"ਸਥਿਤੀ ਬਾਰ ਵਿੱਚ ਘੜੀ ਸਕਿੰਟ ਦਿਖਾਓ। ਬੈਟਰੀ ਸਮਰੱਥਾ ਤੇ ਅਸਰ ਪੈ ਸਕਦਾ ਹੈ।"</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"ਸਥਿਤੀ ਪੱਟੀ ਵਿੱਚ ਘੜੀ ਸਕਿੰਟ ਦਿਖਾਓ। ਬੈਟਰੀ ਸਮਰੱਥਾ ਤੇ ਅਸਰ ਪੈ ਸਕਦਾ ਹੈ।"</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਨੂੰ ਦੁਬਾਰਾ ਕ੍ਰਮ ਦਿਓ"</string>
     <string name="show_brightness" msgid="6613930842805942519">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਚਮਕ ਦਿਖਾਓ"</string>
     <string name="experimental" msgid="6198182315536726162">"ਪ੍ਰਯੋਗਾਤਮਿਕ"</string>
@@ -549,7 +549,7 @@
     <string name="tuner_full_importance_settings" msgid="3207312268609236827">"ਪਾਵਰ ਸੂਚਨਾ ਕੰਟਰੋਲ"</string>
     <string name="tuner_full_importance_settings_on" msgid="7545060756610299966">"ਚਾਲੂ"</string>
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"ਬੰਦ"</string>
-    <string name="power_notification_controls_description" msgid="4372459941671353358">"ਪਾਵਰ ਸੂਚਨਾ ਕੰਟਰੋਲਾਂ ਨਾਲ, ਤੁਸੀਂ ਕਿਸੇ ਐਪ ਦੀਆਂ ਸੂਚਨਾਵਾਂ ਲਈ ਮਹੱਤਤਾ ਪੱਧਰ ਨੂੰ 0 ਤੋਂ 5 ਤੱਕ ਸੈੱਟ ਕਰ ਸਕਦੇ ਹੋ। \n\n"<b>"ਪੱਧਰ 5"</b>" \n- ਸੂਚਨਾ ਸੂਚੀ ਦੇ ਸਿਖਰ \'ਤੇ ਦਿਖਾਓ \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਦੀ ਆਗਿਆ ਦਿਓ \n- ਹਮੇਸ਼ਾਂ ਝਲਕ ਦਿਖਾਓ \n\n"<b>"ਪੱਧਰ 4"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਹਮੇਸ਼ਾਂ ਝਲਕ ਦਿਖਾਓ \n\n"<b>"ਪੱਧਰ 3"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਦਿਖਾਓ \n\n"<b>"ਪੱਧਰ 2"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਦਿਖਾਓ \n- ਕਦੇ ਵੀ ਧੁਨੀ ਜਾਂ ਥਰਥਰਾਹਟ ਨਾ ਕਰੋ \n\n"<b>"ਪੱਧਰ 1"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਦਿਖਾਓ \n- ਕਦੇ ਧੁਨੀ ਜਾਂ ਥਰਥਰਾਹਟ ਨਾ ਕਰੋ \n- ਲੌਕ ਸਕ੍ਰੀਨ ਅਤੇ ਸਥਿਤੀ ਪੱਟੀ ਤੋਂ ਲੁਕਾਓ \n- ਸੂਚਨਾ ਸੂਚੀ ਦੇ ਹੇਠਾਂ ਦਿਖਾਓ \n\n"<b>"ਪੱਧਰ 0"</b>" \n- ਐਪ ਤੋਂ ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਬਲਾਕ ਕਰੋ"</string>
+    <string name="power_notification_controls_description" msgid="4372459941671353358">"ਪਾਵਰ ਸੂਚਨਾ ਕੰਟਰੋਲਾਂ ਨਾਲ, ਤੁਸੀਂ ਕਿਸੇ ਐਪ ਦੀਆਂ ਸੂਚਨਾਵਾਂ ਲਈ ਮਹੱਤਤਾ ਪੱਧਰ ਨੂੰ 0 ਤੋਂ 5 ਤੱਕ ਸੈੱਟ ਕਰ ਸਕਦੇ ਹੋ। \n\n"<b>"ਪੱਧਰ 5"</b>" \n- ਸੂਚਨਾ ਸੂਚੀ ਦੇ ਸਿਖਰ \'ਤੇ ਦਿਖਾਓ \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਦੀ ਆਗਿਆ ਦਿਓ \n- ਹਮੇਸ਼ਾਂ ਝਲਕ ਦਿਖਾਓ \n\n"<b>"ਪੱਧਰ 4"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਹਮੇਸ਼ਾਂ ਝਲਕ ਦਿਖਾਓ \n\n"<b>"ਪੱਧਰ 3"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਦਿਖਾਓ \n\n"<b>"ਪੱਧਰ 2"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਦਿਖਾਓ \n- ਕਦੇ ਵੀ ਧੁਨੀ ਜਾਂ ਥਰਥਰਾਹਟ ਨਾ ਕਰੋ \n\n"<b>"ਪੱਧਰ 1"</b>" \n- ਪੂਰੀ ਸਕ੍ਰੀਨ ਰੁਕਾਵਟ ਨੂੰ ਰੋਕੋ \n- ਕਦੇ ਝਲਕ ਨਾ ਦਿਖਾਓ \n- ਕਦੇ ਧੁਨੀ ਜਾਂ ਥਰਥਰਾਹਟ ਨਾ ਕਰੋ \n- ਲਾਕ ਸਕ੍ਰੀਨ ਅਤੇ ਸਥਿਤੀ ਪੱਟੀ ਤੋਂ ਲੁਕਾਓ \n- ਸੂਚਨਾ ਸੂਚੀ ਦੇ ਹੇਠਾਂ ਦਿਖਾਓ \n\n"<b>"ਪੱਧਰ 0"</b>" \n- ਐਪ ਤੋਂ ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਬਲਾਕ ਕਰੋ"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"ਸੂਚਨਾਵਾਂ"</string>
     <string name="notification_channel_disabled" msgid="2139193533791840539">"ਤੁਹਾਨੂੰ ਹੁਣ ਇਹ ਸੂਚਨਾਵਾਂ ਪ੍ਰਾਪਤ ਨਹੀਂ ਹੋਣਗੀਆਂ"</string>
     <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> ਸੂਚਨਾ ਸ਼੍ਰੇਣੀਆਂ"</string>
@@ -569,7 +569,7 @@
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"ਇਸ ਚੈਨਲ ਤੋਂ ਸੂਚਨਾਵਾਂ ਨੂੰ ਇਜਾਜ਼ਤ ਦਿਓ"</string>
     <string name="notification_all_categories" msgid="5407190218055113282">"ਸਭ ਸ਼੍ਰੇਣੀਆਂ"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"ਹੋਰ ਸੈਟਿੰਗਾਂ"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ ਕਰੋ: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="3743278649182392015">"ਵਿਉਂਤਬੱਧ ਕਰੋ: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
     <string name="notification_done" msgid="5279426047273930175">"ਹੋ ਗਿਆ"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"ਸੂਚਨਾ ਕੰਟਰੋਲ"</string>
@@ -596,19 +596,19 @@
     <string name="keyboard_key_dpad_left" msgid="1346446024676962251">"Left"</string>
     <string name="keyboard_key_dpad_right" msgid="3317323247127515341">"Right"</string>
     <string name="keyboard_key_dpad_center" msgid="2566737770049304658">"Center"</string>
-    <string name="keyboard_key_tab" msgid="3871485650463164476">"Tab"</string>
+    <string name="keyboard_key_tab" msgid="3871485650463164476">"ਟੈਬ"</string>
     <string name="keyboard_key_space" msgid="2499861316311153293">"Space"</string>
     <string name="keyboard_key_enter" msgid="5739632123216118137">"Enter"</string>
     <string name="keyboard_key_backspace" msgid="1559580097512385854">"Backspace"</string>
     <string name="keyboard_key_media_play_pause" msgid="3861975717393887428">"Play/Pause"</string>
     <string name="keyboard_key_media_stop" msgid="2859963958595908962">"Stop"</string>
-    <string name="keyboard_key_media_next" msgid="1894394911630345607">"Next"</string>
-    <string name="keyboard_key_media_previous" msgid="4256072387192967261">"Previous"</string>
+    <string name="keyboard_key_media_next" msgid="1894394911630345607">"ਅੱਗੇ"</string>
+    <string name="keyboard_key_media_previous" msgid="4256072387192967261">"ਪਿਛਲਾ"</string>
     <string name="keyboard_key_media_rewind" msgid="2654808213360820186">"Rewind"</string>
-    <string name="keyboard_key_media_fast_forward" msgid="3849417047738200605">"Fast Forward"</string>
+    <string name="keyboard_key_media_fast_forward" msgid="3849417047738200605">"ਤੇਜ਼ੀ ਨਾਲ ਅੱਗੇ ਭੇਜੋ"</string>
     <string name="keyboard_key_page_up" msgid="5654098530106845603">"Page Up"</string>
     <string name="keyboard_key_page_down" msgid="8720502083731906136">"Page Down"</string>
-    <string name="keyboard_key_forward_del" msgid="1391451334716490176">"Delete"</string>
+    <string name="keyboard_key_forward_del" msgid="1391451334716490176">"ਮਿਟਾਓ"</string>
     <string name="keyboard_key_move_home" msgid="2765693292069487486">"Home"</string>
     <string name="keyboard_key_move_end" msgid="5901174332047975247">"End"</string>
     <string name="keyboard_key_insert" msgid="8530501581636082614">"Insert"</string>
@@ -637,7 +637,7 @@
     <string name="battery" msgid="7498329822413202973">"ਬੈਟਰੀ"</string>
     <string name="clock" msgid="7416090374234785905">"ਘੜੀ"</string>
     <string name="headset" msgid="4534219457597457353">"ਹੈੱਡਸੈੱਟ"</string>
-    <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ਹੈੱਡਫੋਨਾਂ ਨੂੰ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"ਹੈੱਡਫ਼ੋਨ ਨੂੰ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"ਹੈੱਡਸੈੱਟ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
     <string name="data_saver" msgid="5037565123367048522">"ਡਾਟਾ ਸੇਵਰ"</string>
     <string name="accessibility_data_saver_on" msgid="8454111686783887148">"ਡਾਟਾ ਸੇਵਰ ਚਾਲੂ ਹੈ"</string>
@@ -666,7 +666,7 @@
     <string name="reset" msgid="2448168080964209908">"ਰੀਸੈੱਟ ਕਰੋ"</string>
     <string name="adjust_button_width" msgid="6138616087197632947">"ਬਟਨ ਚੁੜਾਈ ਵਿਵਸਥਿਤ ਕਰੋ"</string>
     <string name="clipboard" msgid="1313879395099896312">"ਕਲਿੱਪਬੋਰਡ"</string>
-    <string name="accessibility_key" msgid="5701989859305675896">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ ਆਵਾਗੌਣ ਬਟਨ"</string>
+    <string name="accessibility_key" msgid="5701989859305675896">"ਵਿਉਂਂਤੀ ਨੈਵੀਗੇਟ ਬਟਨ"</string>
     <string name="left_keycode" msgid="2010948862498918135">"ਖੱਬਾ ਕੀ-ਕੋਡ"</string>
     <string name="right_keycode" msgid="708447961000848163">"ਸੱਜਾ ਕੀ-ਕੋਡ"</string>
     <string name="left_icon" msgid="3096287125959387541">"ਖੱਬਾ ਪ੍ਰਤੀਕ"</string>
@@ -678,12 +678,12 @@
   <string-array name="clock_options">
     <item msgid="5965318737560463480">"ਘੰਟੇ, ਮਿੰਟ, ਅਤੇ ਸਕਿੰਟ  ਦਿਖਾਓ"</item>
     <item msgid="1427801730816895300">"ਘੰਟੇ ਅਤੇ ਮਿੰਟ ਦਿਖਾਓ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
-    <item msgid="3830170141562534721">"ਇਸ ਚਿੰਨ੍ਹ ਨੂੰ ਨਾ  ਦਿਖਾਓ"</item>
+    <item msgid="3830170141562534721">"ਇਸ ਪ੍ਰਤੀਕ ਨੂੰ ਨਾ ਦਿਖਾਓ"</item>
   </string-array>
   <string-array name="battery_options">
     <item msgid="3160236755818672034">"ਹਮੇਸ਼ਾਂ ਪ੍ਰਤੀਸ਼ਤਤਾ  ਦਿਖਾਓ"</item>
     <item msgid="2139628951880142927">"ਚਾਰਜਿੰਗ ਦੌਰਾਨ ਪ੍ਰਤੀਸ਼ਤਤਾ ਦਿਖਾਓ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
-    <item msgid="3327323682209964956">"ਇਸ ਚਿੰਨ੍ਹ ਨੂੰ ਨਾ  ਦਿਖਾਓ"</item>
+    <item msgid="3327323682209964956">"ਇਸ ਪ੍ਰਤੀਕ ਨੂੰ ਨਾ ਦਿਖਾਓ"</item>
   </string-array>
     <string name="other" msgid="4060683095962566764">"ਹੋਰ"</string>
     <string name="accessibility_divider" msgid="5903423481953635044">"ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਡਿਵਾਈਡਰ"</string>
@@ -697,8 +697,8 @@
     <string name="accessibility_action_divider_top_50" msgid="6385859741925078668">"ਉੱਪਰ 50%"</string>
     <string name="accessibility_action_divider_top_30" msgid="6201455163864841205">"ਉੱਪਰ 30%"</string>
     <string name="accessibility_action_divider_bottom_full" msgid="301433196679548001">"ਹੇਠਾਂ ਪੂਰੀ ਸਕ੍ਰੀਨ"</string>
-    <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"ਸਥਿਤੀ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>। ਸੰਪਾਦਨ ਲਈ ਡਬਲ ਟੈਪ ਕਰੋ।"</string>
-    <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>। ਸ਼ਾਮਲ ਕਰਨ ਲਈ ਡਬਲ ਟੈਪ ਕਰੋ।"</string>
+    <string name="accessibility_qs_edit_tile_label" msgid="8374924053307764245">"ਸਥਿਤੀ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>। ਸੰਪਾਦਨ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰੋ।"</string>
+    <string name="accessibility_qs_edit_add_tile_label" msgid="8133209638023882667">"<xliff:g id="TILE_NAME">%1$s</xliff:g>। ਸ਼ਾਮਲ ਕਰਨ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰੋ।"</string>
     <string name="accessibility_qs_edit_position_label" msgid="5055306305919289819">"ਸਥਿਤੀ <xliff:g id="POSITION">%1$d</xliff:g>। ਚੁਣਨ ਲਈ ਡਬਲ ਟੈਪ ਕਰੋ।"</string>
     <string name="accessibility_qs_edit_move_tile" msgid="2461819993780159542">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ਨੂੰ ਤਬਦੀਲ ਕਰੋ"</string>
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ਹਟਾਓ"</string>
@@ -735,7 +735,7 @@
     <string name="pip_skip_to_prev" msgid="1955311326688637914">"ਪਿਛਲੇ \'ਤੇ ਜਾਓ"</string>
     <string name="thermal_shutdown_title" msgid="4458304833443861111">"ਗਰਮ ਹੋਣ ਕਾਰਨ ਫ਼ੋਨ ਬੰਦ ਹੋ ਗਿਆ"</string>
     <string name="thermal_shutdown_message" msgid="9006456746902370523">"ਤੁਹਾਡਾ ਫ਼ੋਨ ਹੁਣ ਸਹੀ ਚੱਲ ਰਿਹਾ ਹੈ"</string>
-    <string name="thermal_shutdown_dialog_message" msgid="566347880005304139">"ਤੁਹਾਡਾ ਫ਼ੋਨ ਬਹੁਤ ਗਰਮ ਸੀ, ਇਸ ਲਈ ਇਹ ਠੰਡਾ ਹੋਣ ਵਾਸਤੇ ਬੰਦ ਹੋ ਗਿਆ ਸੀ। ਤੁਹਾਡਾ ਫ਼ੋਨ ਹੁਣ ਸਹੀ ਚੱਲ ਰਿਹਾ ਹੈ।\n\nਤੁਹਾਡਾ ਫ਼ੋਨ ਬਹੁਤ ਗਰਮ ਹੋ ਸਕਦਾ ਹੈ ਜੇ:\n	• ਤੁਸੀਂ ਸਰੋਤਾਂ ਦੀ ਵੱਧ ਵਰਤੋਂ ਵਾਲੀਆਂ ਐਪਾਂ (ਜਿਵੇਂ ਗੇਮਿੰਗ, ਵੀਡੀਓ, ਜਾਂ ਦਿਸ਼ਾ-ਨਿਰਦੇਸ਼ ਐਪਾਂ) ਵਰਤਦੇ ਹੋ \n	• ਵੱਡੀਆਂ ਫ਼ਾਈਲਾਂ ਡਾਊਨਲੋਡ ਜਾਂ ਅੱਪਲੋਡ ਕਰਦੇ ਹੋ\n	• ਆਪਣੇ ਫ਼ੋਨ ਨੂੰ ਉੱਚ ਤਾਪਮਾਨਾਂ ਵਿੱਚ ਵਰਤਦੇ ਹੋ"</string>
+    <string name="thermal_shutdown_dialog_message" msgid="566347880005304139">\n"ਤੁਹਾਡਾ ਫ਼ੋਨ ਬਹੁਤ ਗਰਮ ਸੀ, ਇਸ ਲਈ ਇਹ ਠੰਡਾ ਹੋਣ ਵਾਸਤੇ ਬੰਦ ਹੋ ਗਿਆ ਸੀ। ਤੁਹਾਡਾ ਫ਼ੋਨ ਹੁਣ ਸਹੀ ਚੱਲ ਰਿਹਾ ਹੈ।\n\nਤੁਹਾਡਾ ਫ਼ੋਨ ਬਹੁਤ ਗਰਮ ਹੋ ਸਕਦਾ ਹੈ ਜੇ:\n	• ਤੁਸੀਂ ਸਰੋਤਾਂ ਦੀ ਵੱਧ ਵਰਤੋਂ ਵਾਲੀਆਂ ਐਪਾਂ (ਜਿਵੇਂ ਗੇਮਿੰਗ, ਵੀਡੀਓ, ਜਾਂ ਦਿਸ਼ਾ-ਨਿਰਦੇਸ਼ ਐਪਾਂ) ਵਰਤਦੇ ਹੋ 	• ਵੱਡੀਆਂ ਫ਼ਾਈਲਾਂ ਡਾਊਨਲੋਡ ਜਾਂ ਅੱਪਲੋਡ ਕਰਦੇ ਹੋ\n	• ਆਪਣੇ ਫ਼ੋਨ ਨੂੰ ਉੱਚ ਤਾਪਮਾਨਾਂ ਵਿੱਚ ਵਰਤਦੇ ਹੋ"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"ਫ਼ੋਨ ਗਰਮ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"ਫ਼ੋਨ ਦੇ ਠੰਡਾ ਹੋਣ ਦੇ ਦੌਰਾਨ ਕੁਝ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਸੀਮਿਤ ਹੁੰਦੀਆਂ ਹਨ"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"ਤੁਹਾਡਾ ਫ਼ੋਨ ਸਵੈਚਲਿਤ ਰੂਪ ਵਿੱਚ ਠੰਡਾ ਹੋਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੇਗਾ। ਤੁਸੀਂ ਹਾਲੇ ਵੀ ਆਪਣੇ ਫ਼ੋਨ ਨੂੰ ਵਰਤ ਸਕਦੇ ਹੋ, ਪਰੰਤੂ ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਇਹ ਵਧੇਰੇ ਹੌਲੀ ਚੱਲੇ।\n\nਇੱਕ ਵਾਰ ਠੰਡਾ ਹੋਣ ਤੋਂ ਬਾਅਦ ਤੁਹਾਡਾ ਫ਼ੋਨ ਸਧਾਰਨ ਤੌਰ \'ਤੇ ਚੱਲੇਗਾ।"</string>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 745d6015..a923f0b 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -34,6 +34,7 @@
         <attr name="recentItemLayout" format="reference" />
         <!-- Style for the "Clear all" button. -->
         <attr name="clearAllStyle" format="reference" />
+        <attr name="clearAllBackgroundColor" format="reference" />
     </declare-styleable>
     <declare-styleable name="DeadZone">
         <attr name="minSize" format="dimension" />
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index f72f379..f244d88 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -60,6 +60,11 @@
     <!-- The background color for the freeform workspace. -->
     <color name="recents_freeform_workspace_bg_color">#33FFFFFF</color>
 
+    <!-- The background color for clear all button on light backgrounds if not transparent. -->
+    <color name="recents_clear_all_button_bg_light_color">#CCFFFFFF</color>
+    <!-- The background color for clear all button on dark backgrounds if not transparent. -->
+    <color name="recents_clear_all_button_bg_dark_color">#CC000000</color>
+
     <color name="keyguard_affordance">#ffffffff</color>
 
     <!-- The color of the legacy notification background -->
diff --git a/packages/SystemUI/res/values/colors_car.xml b/packages/SystemUI/res/values/colors_car.xml
index 1b8c2fa..710b3e0 100644
--- a/packages/SystemUI/res/values/colors_car.xml
+++ b/packages/SystemUI/res/values/colors_car.xml
@@ -20,8 +20,12 @@
     <color name="car_qs_background_primary">#263238</color> <!-- Blue Gray 900 -->
     <color name="car_user_switcher_progress_bgcolor">#00000000</color> <!-- Transparent -->
     <color name="car_user_switcher_progress_fgcolor">#80CBC4</color> <!-- Teal 200 -->
-    <color name="car_user_switcher_no_user_image_bgcolor">#FAFAFA</color> <!-- Grey 50 -->
-    <color name="car_user_switcher_no_user_image_fgcolor">#212121</color> <!-- Grey 900 -->
-    <color name="car_start_driving_background">#FAFAFA</color> <!-- Grey 50 -->
-    <color name="car_start_driving_text">#212121</color> <!-- Grey 900 -->
+    <color name="car_user_switcher_no_user_image_bgcolor">@color/car_grey_50</color>
+    <color name="car_user_switcher_no_user_image_fgcolor">@color/car_grey_900</color>
+    <color name="car_start_driving_background">@color/car_grey_50</color>
+    <color name="car_start_driving_text">@color/car_grey_900</color>
+    <color name="car_qs_footer_user_name_color">@color/car_grey_50</color>
+
+    <color name="car_grey_50">#FAFAFA</color>
+    <color name="car_grey_900">#212121</color>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index bcaafcc..e6a357f 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -80,6 +80,12 @@
     <!-- Height of a small notification in the status bar which was used before android N -->
     <dimen name="notification_min_height_legacy">64dp</dimen>
 
+    <!-- The increase in minHeight that is allowed when the notification is colorized -->
+    <dimen name="notification_height_increase_colorized">11sp</dimen>
+
+    <!-- The increase in minHeight that is allowed when the notification is colorized and has increased height (i.e messages) -->
+    <dimen name="notification_height_increase_colorized_increased">13sp</dimen>
+
     <!-- Height of a large notification in the status bar -->
     <dimen name="notification_max_height">284dp</dimen>
 
@@ -298,6 +304,7 @@
     <dimen name="qs_detail_padding_start">16dp</dimen>
     <dimen name="qs_detail_items_padding_top">4dp</dimen>
     <dimen name="qs_detail_item_icon_size">24dp</dimen>
+    <dimen name="qs_detail_item_icon_width">32dp</dimen>
     <dimen name="qs_detail_item_icon_marginStart">0dp</dimen>
     <dimen name="qs_detail_item_icon_marginEnd">20dp</dimen>
     <dimen name="qs_footer_padding_start">16dp</dimen>
diff --git a/packages/SystemUI/res/values/dimens_car.xml b/packages/SystemUI/res/values/dimens_car.xml
index 5f56c4e..8853587 100644
--- a/packages/SystemUI/res/values/dimens_car.xml
+++ b/packages/SystemUI/res/values/dimens_car.xml
@@ -18,7 +18,8 @@
 <resources>
     <dimen name="car_margin">148dp</dimen>
 
-    <dimen name="car_fullscreen_user_pod_margin_above_text">24dp</dimen>
+    <dimen name="car_fullscreen_user_pod_margin_name_top">24dp</dimen>
+    <dimen name="car_fullscreen_user_pod_margin_name_bottom">64dp</dimen>
     <dimen name="car_fullscreen_user_pod_margin_between">24dp</dimen>
     <dimen name="car_fullscreen_user_pod_icon_text_size">96dp</dimen>
     <dimen name="car_fullscreen_user_pod_image_avatar_width">192dp</dimen>
@@ -37,5 +38,17 @@
     <dimen name="car_start_driving_corner_radius">16dp</dimen>
     <dimen name="car_start_driving_padding_side">30dp</dimen>
     <dimen name="car_start_driving_height">80dp</dimen>
-    <dimen name="car_start_driving_text_size">32sp</dimen> <!-- B2 -->
+    <dimen name="car_start_driving_text_size">@dimen/car_body2_size</dimen>
+
+    <dimen name="car_qs_footer_height">112dp</dimen>
+    <dimen name="car_qs_footer_padding_bottom">16dp</dimen>
+    <dimen name="car_qs_footer_padding_top">16dp</dimen>
+    <dimen name="car_qs_footer_padding_end">46dp</dimen>
+    <dimen name="car_qs_footer_padding_start">46dp</dimen>
+    <dimen name="car_qs_footer_icon_width">56dp</dimen>
+    <dimen name="car_qs_footer_icon_height">56dp</dimen>
+    <dimen name="car_qs_footer_user_switch_margin_right">46dp</dimen>
+    <dimen name="car_qs_footer_user_name_text_size">@dimen/car_body2_size</dimen>
+
+    <dimen name="car_body2_size">26sp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index b27dedd..2148c80 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -59,6 +59,7 @@
     <item type="id" name="transformation_start_y_tag"/>
     <item type="id" name="transformation_start_scale_x_tag"/>
     <item type="id" name="transformation_start_scale_y_tag"/>
+    <item type="id" name="continuous_clipping_tag"/>
 
     <!-- Whether the icon is from a notification for which targetSdk < L -->
     <item type="id" name="icon_is_pre_L"/>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 2199fff..90c5977 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -34,11 +34,13 @@
         <item name="android:windowShowWallpaper">true</item>
         <item name="android:windowDisablePreview">true</item>
         <item name="clearAllStyle">@style/ClearAllButtonDefaultMargins</item>
+        <item name="clearAllBackgroundColor">@color/recents_clear_all_button_bg_dark_color</item>
         <item name="wallpaperTextColor">@*android:color/primary_text_material_dark</item>
         <item name="wallpaperTextColorSecondary">@*android:color/secondary_text_material_dark</item>
     </style>
 
     <style name="RecentsTheme.Wallpaper.Light">
+        <item name="clearAllBackgroundColor">@color/recents_clear_all_button_bg_light_color</item>
         <item name="wallpaperTextColor">@*android:color/primary_text_material_light</item>
         <item name="wallpaperTextColorSecondary">@*android:color/secondary_text_material_light</item>
     </style>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
index 8de1d31..2bc0e45c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -15,6 +15,8 @@
  */
 package com.android.keyguard;
 
+import static android.view.Display.INVALID_DISPLAY;
+
 import android.app.Presentation;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -28,16 +30,21 @@
 import android.view.View;
 import android.view.WindowManager;
 
+// TODO(multi-display): Support multiple external displays
 public class KeyguardDisplayManager {
     protected static final String TAG = "KeyguardDisplayManager";
     private static boolean DEBUG = KeyguardConstants.DEBUG;
+
+    private final ViewMediatorCallback mCallback;
+    private final MediaRouter mMediaRouter;
+    private final Context mContext;
+
     Presentation mPresentation;
-    private MediaRouter mMediaRouter;
-    private Context mContext;
     private boolean mShowing;
 
-    public KeyguardDisplayManager(Context context) {
+    public KeyguardDisplayManager(Context context, ViewMediatorCallback callback) {
         mContext = context;
+        mCallback = callback;
         mMediaRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
     }
 
@@ -90,6 +97,7 @@
     };
 
     protected void updateDisplays(boolean showing) {
+        Presentation originalPresentation = mPresentation;
         if (showing) {
             MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute(
                     MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY);
@@ -121,6 +129,13 @@
                 mPresentation = null;
             }
         }
+
+        // mPresentation is only updated when the display changes
+        if (mPresentation != originalPresentation) {
+            final int displayId = mPresentation != null
+                    ? mPresentation.getDisplay().getDisplayId() : INVALID_DISPLAY;
+            mCallback.onSecondaryDisplayShowingChanged(displayId);
+        }
     }
 
     private final static class KeyguardPresentation extends Presentation {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index c596398..d95402c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -50,6 +50,7 @@
 import android.os.BatteryManager;
 import android.os.CancellationSignal;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.IRemoteCallback;
 import android.os.Message;
 import android.os.RemoteException;
@@ -58,6 +59,8 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.service.dreams.DreamService;
+import android.service.dreams.IDreamManager;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -67,8 +70,6 @@
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 
-import com.google.android.collect.Lists;
-
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.IccCardConstants.State;
 import com.android.internal.telephony.PhoneConstants;
@@ -77,6 +78,8 @@
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
 
+import com.google.android.collect.Lists;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
@@ -217,6 +220,8 @@
     private UserManager mUserManager;
     private int mFingerprintRunningState = FINGERPRINT_STATE_STOPPED;
     private LockPatternUtils mLockPatternUtils;
+    private final IDreamManager mDreamManager;
+    private boolean mIsDreaming;
 
     /**
      * Short delay before restarting fingerprint authentication after a successful try
@@ -458,6 +463,26 @@
         updateFingerprintListeningState();
     }
 
+    /**
+     * @return a cached version of DreamManager.isDreaming()
+     */
+    public boolean isDreaming() {
+        return mIsDreaming;
+    }
+
+    /**
+     * If the device is dreaming, awakens the device
+     */
+    public void awakenFromDream() {
+        if (mIsDreaming && mDreamManager != null) {
+            try {
+                mDreamManager.awaken();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Unable to awaken from dream");
+            }
+        }
+    }
+
     private void onFingerprintAuthenticated(int userId) {
         Trace.beginSection("KeyGuardUpdateMonitor#onFingerPrintAuthenticated");
         mUserFingerprintAuthenticated.put(userId, true);
@@ -1037,11 +1062,11 @@
 
     private void handleDreamingStateChanged(int dreamStart) {
         final int count = mCallbacks.size();
-        boolean showingDream = dreamStart == 1;
+        mIsDreaming = dreamStart == 1;
         for (int i = 0; i < count; i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
-                cb.onDreamingStateChanged(showingDream);
+                cb.onDreamingStateChanged(mIsDreaming);
             }
         }
     }
@@ -1146,6 +1171,9 @@
         mLockPatternUtils = new LockPatternUtils(context);
         mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker);
 
+        mDreamManager = IDreamManager.Stub.asInterface(
+                ServiceManager.getService(DreamService.DREAM_SERVICE));
+
         if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
             mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
         }
@@ -1183,7 +1211,7 @@
     private boolean shouldListenForFingerprint() {
         return (mKeyguardIsVisible || !mDeviceInteractive ||
                 (mBouncer && !mKeyguardGoingAway) || mGoingToSleep ||
-                shouldListenForFingerprintAssistant())
+                shouldListenForFingerprintAssistant() || (mKeyguardOccluded && mIsDreaming))
                 && !mSwitchingUser && !isFingerprintDisabled(getCurrentUser())
                 && !mKeyguardGoingAway;
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java b/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java
index 327d218..b194de4 100644
--- a/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java
@@ -88,4 +88,9 @@
      *         {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}.
      */
     int getBouncerPromptReason();
+
+    /**
+     * Invoked when the secondary display showing a keyguard window changes.
+     */
+    void onSecondaryDisplayShowingChanged(int displayId);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 97a5962..a9a915b 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -42,6 +42,7 @@
 import com.android.systemui.power.PowerUI;
 import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
 import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
+import com.android.systemui.statusbar.phone.LightBarController;
 import com.android.systemui.statusbar.phone.ManagedProfileController;
 import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -296,12 +297,13 @@
 
         mProviders.put(UiOffloadThread.class, UiOffloadThread::new);
 
-
         mProviders.put(PowerUI.WarningsUI.class, () -> new PowerNotificationWarnings(mContext));
 
         mProviders.put(IconLogger.class, () -> new IconLoggerImpl(mContext,
                 getDependency(BG_LOOPER), getDependency(MetricsLogger.class)));
 
+        mProviders.put(LightBarController.class, () -> new LightBarController(mContext));
+
         // Put all dependencies above here so the factory can override them if it wants.
         SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 9b1842a..6f8bcff 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -58,22 +58,20 @@
                 params);
 
         DozeMachine machine = new DozeMachine(wrappedService, config, wakeLock);
-        DozeScreenBrightness screenBrightness = createDozeScreenBrightness(
-                context, wrappedService, sensorManager, host, handler);
         machine.setParts(new DozeMachine.Part[]{
                 new DozePauser(handler, machine, alarmManager, new AlwaysOnDisplayPolicy(context)),
                 new DozeFalsingManagerAdapter(FalsingManager.getInstance(context)),
                 createDozeTriggers(context, sensorManager, host, alarmManager, config, params,
-                        handler, screenBrightness, wakeLock, machine),
+                        handler, wakeLock, machine),
                 createDozeUi(context, host, wakeLock, machine, handler, alarmManager),
                 new DozeScreenState(wrappedService, handler),
-                screenBrightness,
+                createDozeScreenBrightness(context, wrappedService, sensorManager, host, handler),
         });
 
         return machine;
     }
 
-    private DozeScreenBrightness createDozeScreenBrightness(Context context,
+    private DozeMachine.Part createDozeScreenBrightness(Context context,
             DozeMachine.Service service, SensorManager sensorManager, DozeHost host,
             Handler handler) {
         Sensor sensor = DozeSensors.findSensorWithType(sensorManager,
@@ -84,11 +82,10 @@
 
     private DozeTriggers createDozeTriggers(Context context, SensorManager sensorManager,
             DozeHost host, AlarmManager alarmManager, AmbientDisplayConfiguration config,
-            DozeParameters params, Handler handler, DozeScreenBrightness screenBrightness,
-            WakeLock wakeLock, DozeMachine machine) {
+            DozeParameters params, Handler handler, WakeLock wakeLock, DozeMachine machine) {
         boolean allowPulseTriggers = true;
         return new DozeTriggers(context, machine, host, alarmManager, config, params,
-                sensorManager, handler, screenBrightness, wakeLock, allowPulseTriggers);
+                sensorManager, handler, wakeLock, allowPulseTriggers);
     }
 
     private DozeMachine.Part createDozeUi(Context context, DozeHost host, WakeLock wakeLock,
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index 92f8d8c..03407e2 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -37,10 +37,11 @@
     private final Sensor mLightSensor;
     private final int[] mSensorToBrightness;
     private final int[] mSensorToScrimOpacity;
+
     private boolean mRegistered;
-    private boolean mReady = true;
-    private ReadyListener mReadyListener;
     private int mDefaultDozeBrightness;
+    private boolean mPaused = false;
+    private int mLastSensorValue = -1;
 
     public DozeScreenBrightness(Context context, DozeMachine.Service service,
             SensorManager sensorManager, Sensor lightSensor, DozeHost host,
@@ -86,22 +87,38 @@
                 setLightSensorEnabled(false);
                 break;
         }
+        if (newState != DozeMachine.State.FINISH) {
+            setPaused(newState == DozeMachine.State.DOZE_AOD_PAUSED);
+        }
     }
 
     @Override
     public void onSensorChanged(SensorEvent event) {
         if (mRegistered) {
-            int sensorValue = (int) event.values[0];
-            int brightness = computeBrightness(sensorValue);
-            if (brightness > 0) {
+            mLastSensorValue = (int) event.values[0];
+            updateBrightnessAndReady();
+        }
+    }
+
+    private void updateBrightnessAndReady() {
+        if (mRegistered) {
+            int brightness = computeBrightness(mLastSensorValue);
+            boolean brightnessReady = brightness > 0;
+            if (brightnessReady) {
                 mDozeService.setDozeScreenBrightness(brightness);
             }
-            // If the brightness is zero or negative, this indicates that the brightness sensor is
-            // covered or reports that the screen should be off, therefore we're not ready to turn
-            // on the screen yet.
-            setReady(brightness > 0);
 
-            int scrimOpacity = computeScrimOpacity(sensorValue);
+            int scrimOpacity = -1;
+            if (mPaused) {
+                // If AOD is paused, force the screen black until the
+                // sensor reports a new brightness. This ensures that when the screen comes on
+                // again, it will only show after the brightness sensor has stabilized,
+                // avoiding a potential flicker.
+                scrimOpacity = 255;
+            } else if (brightnessReady) {
+                // Only unblank scrim once brightness is ready.
+                scrimOpacity = computeScrimOpacity(mLastSensorValue);
+            }
             if (scrimOpacity >= 0) {
                 mDozeHost.setAodDimmingScrim(scrimOpacity / 255f);
             }
@@ -128,47 +145,28 @@
 
     private void resetBrightnessToDefault() {
         mDozeService.setDozeScreenBrightness(mDefaultDozeBrightness);
+        mDozeHost.setAodDimmingScrim(0f);
     }
 
     private void setLightSensorEnabled(boolean enabled) {
         if (enabled && !mRegistered && mLightSensor != null) {
             // Wait until we get an event from the sensor until indicating ready.
-            setReady(false);
             mRegistered = mSensorManager.registerListener(this, mLightSensor,
                     SensorManager.SENSOR_DELAY_NORMAL, mHandler);
+            mLastSensorValue = -1;
         } else if (!enabled && mRegistered) {
             mSensorManager.unregisterListener(this);
             mRegistered = false;
+            mLastSensorValue = -1;
             // Sensor is not enabled, hence we use the default brightness and are always ready.
-            setReady(true);
         }
     }
 
-    private void setReady(boolean ready) {
-        if (ready != mReady) {
-            mReady = ready;
-            if (mReadyListener != null) {
-                mReadyListener.onBrightnessReadyChanged(mReady);
-            }
+    private void setPaused(boolean paused) {
+        if (mPaused != paused) {
+            mPaused = paused;
+            updateBrightnessAndReady();
         }
     }
 
-    public void setBrightnessReadyListener(ReadyListener l) {
-        mReadyListener = l;
-        l.onBrightnessReadyChanged(mReady);
-    }
-
-    /**
-     * @return true if the screen brightness is properly calculated.
-     *
-     * Can be used to wait for transitioning out of the paused state, such that we don't turn the
-     * display on before the display brightness is properly calculated.
-     */
-    public boolean isReady() {
-        return mReady;
-    }
-
-    public interface ReadyListener {
-        void onBrightnessReadyChanged(boolean ready);
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 8d8c55c..f7a258a 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -33,7 +33,6 @@
 import android.text.format.Formatter;
 import android.util.Log;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.internal.util.Preconditions;
 import com.android.systemui.statusbar.phone.DozeParameters;
@@ -66,7 +65,6 @@
     private final boolean mAllowPulseTriggers;
     private final UiModeManager mUiModeManager;
     private final TriggerReceiver mBroadcastReceiver = new TriggerReceiver();
-    private final DozeScreenBrightness mDozeScreenBrightness;
 
     private long mNotificationPulseTime;
     private boolean mPulsePending;
@@ -75,7 +73,7 @@
     public DozeTriggers(Context context, DozeMachine machine, DozeHost dozeHost,
             AlarmManager alarmManager, AmbientDisplayConfiguration config,
             DozeParameters dozeParameters, SensorManager sensorManager, Handler handler,
-            DozeScreenBrightness brightness, WakeLock wakeLock, boolean allowPulseTriggers) {
+            WakeLock wakeLock, boolean allowPulseTriggers) {
         mContext = context;
         mMachine = machine;
         mDozeHost = dozeHost;
@@ -89,7 +87,6 @@
                 config, wakeLock, this::onSensor, this::onProximityFar,
                 new AlwaysOnDisplayPolicy(context));
         mUiModeManager = mContext.getSystemService(UiModeManager.class);
-        mDozeScreenBrightness = brightness;
     }
 
     private void onNotification() {
@@ -162,41 +159,16 @@
     private void onProximityFar(boolean far) {
         final boolean near = !far;
         final DozeMachine.State state = mMachine.getState();
+        final boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED);
+        final boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING);
+        final boolean aod = (state == DozeMachine.State.DOZE_AOD);
 
         if (state == DozeMachine.State.DOZE_PULSING) {
             boolean ignoreTouch = near;
             if (DEBUG) Log.i(TAG, "Prox changed, ignore touch = " + ignoreTouch);
             mDozeHost.onIgnoreTouchWhilePulsing(ignoreTouch);
         }
-
-        recalculatePausing();
-    }
-
-    private void onBrightnessReady(boolean brightnessReady) {
-        // Post because this is sometimes called during state transitions and we cannot query
-        // the machine's state while it's transitioning.
-        mHandler.post(this::recalculatePausing);
-    }
-
-    private void recalculatePausing() {
-        boolean brightnessReady = mDozeScreenBrightness.isReady();
-        Boolean proxCurrentlyFar = mDozeSensors.isProximityCurrentlyFar();
-
-        // Treat UNKNOWN the same as FAR, such that we don't pause the display just because
-        // the prox has unknown state.
-        boolean proximityFar = proxCurrentlyFar == null || proxCurrentlyFar;
-        recalculatePausing(proximityFar, brightnessReady);
-    }
-
-    @VisibleForTesting
-    void recalculatePausing(boolean proximityFar, boolean brightnessReady) {
-        final boolean near = !proximityFar;
-        final DozeMachine.State state = mMachine.getState();
-        final boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED);
-        final boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING);
-        final boolean aod = (state == DozeMachine.State.DOZE_AOD);
-
-        if (proximityFar && (pausing || paused && brightnessReady)) {
+        if (far && (paused || pausing)) {
             if (DEBUG) Log.i(TAG, "Prox FAR, unpausing AOD");
             mMachine.requestState(DozeMachine.State.DOZE_AOD);
         } else if (near && aod) {
@@ -211,7 +183,6 @@
             case INITIALIZED:
                 mBroadcastReceiver.register(mContext);
                 mDozeHost.addCallback(mHostCallback);
-                mDozeScreenBrightness.setBrightnessReadyListener(this::onBrightnessReady);
                 checkTriggersAtInit();
                 break;
             case DOZE:
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 3eb68f5..28adca9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -17,6 +17,7 @@
 package com.android.systemui.keyguard;
 
 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+import static android.view.Display.INVALID_DISPLAY;
 
 import static com.android.internal.telephony.IccCardConstants.State.ABSENT;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
@@ -239,6 +240,9 @@
     // answer whether the input should be restricted)
     private boolean mShowing;
 
+    // display id of the secondary display on which we have put a keyguard window
+    private int mSecondaryDisplayShowing = INVALID_DISPLAY;
+
     /** Cached value of #isInputRestricted */
     private boolean mInputRestricted;
 
@@ -646,6 +650,13 @@
             }
             return KeyguardSecurityView.PROMPT_REASON_NONE;
         }
+
+        @Override
+        public void onSecondaryDisplayShowingChanged(int displayId) {
+            synchronized (KeyguardViewMediator.this) {
+                setShowingLocked(mShowing, displayId, false);
+            }
+        }
     };
 
     public void userActivity() {
@@ -670,7 +681,7 @@
         filter.addAction(Intent.ACTION_SHUTDOWN);
         mContext.registerReceiver(mBroadcastReceiver, filter);
 
-        mKeyguardDisplayManager = new KeyguardDisplayManager(mContext);
+        mKeyguardDisplayManager = new KeyguardDisplayManager(mContext, mViewMediatorCallback);
 
         mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
 
@@ -685,7 +696,8 @@
                 com.android.keyguard.R.bool.config_enableKeyguardService)) {
             setShowingLocked(!shouldWaitForProvisioning()
                     && !mLockPatternUtils.isLockScreenDisabled(
-                            KeyguardUpdateMonitor.getCurrentUser()), true /* forceCallbacks */);
+                            KeyguardUpdateMonitor.getCurrentUser()),
+                    mSecondaryDisplayShowing, true /* forceCallbacks */);
         }
 
         mStatusBarKeyguardViewManager =
@@ -1694,10 +1706,10 @@
         playSound(mTrustedSoundId);
     }
 
-    private void updateActivityLockScreenState(boolean showing) {
+    private void updateActivityLockScreenState(boolean showing, int secondaryDisplayShowing) {
         mUiOffloadThread.submit(() -> {
             try {
-                ActivityManager.getService().setLockScreenShown(showing);
+                ActivityManager.getService().setLockScreenShown(showing, secondaryDisplayShowing);
             } catch (RemoteException e) {
             }
         });
@@ -2060,30 +2072,39 @@
     }
 
     private void setShowingLocked(boolean showing) {
-        setShowingLocked(showing, false /* forceCallbacks */);
+        setShowingLocked(showing, mSecondaryDisplayShowing, false /* forceCallbacks */);
     }
 
-    private void setShowingLocked(boolean showing, boolean forceCallbacks) {
-        if (showing != mShowing || forceCallbacks) {
+    private void setShowingLocked(
+            boolean showing, int secondaryDisplayShowing, boolean forceCallbacks) {
+        final boolean notifyDefaultDisplayCallbacks = showing != mShowing || forceCallbacks;
+        if (notifyDefaultDisplayCallbacks || secondaryDisplayShowing != mSecondaryDisplayShowing) {
             mShowing = showing;
-            int size = mKeyguardStateCallbacks.size();
-            for (int i = size - 1; i >= 0; i--) {
-                IKeyguardStateCallback callback = mKeyguardStateCallbacks.get(i);
-                try {
-                    callback.onShowingStateChanged(showing);
-                } catch (RemoteException e) {
-                    Slog.w(TAG, "Failed to call onShowingStateChanged", e);
-                    if (e instanceof DeadObjectException) {
-                        mKeyguardStateCallbacks.remove(callback);
-                    }
+            mSecondaryDisplayShowing = secondaryDisplayShowing;
+            if (notifyDefaultDisplayCallbacks) {
+                notifyDefaultDisplayCallbacks(showing);
+            }
+            updateActivityLockScreenState(showing, secondaryDisplayShowing);
+        }
+    }
+
+    private void notifyDefaultDisplayCallbacks(boolean showing) {
+        int size = mKeyguardStateCallbacks.size();
+        for (int i = size - 1; i >= 0; i--) {
+            IKeyguardStateCallback callback = mKeyguardStateCallbacks.get(i);
+            try {
+                callback.onShowingStateChanged(showing);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Failed to call onShowingStateChanged", e);
+                if (e instanceof DeadObjectException) {
+                    mKeyguardStateCallbacks.remove(callback);
                 }
             }
-            updateInputRestrictedLocked();
-            mUiOffloadThread.submit(() -> {
-                mTrustManager.reportKeyguardShowingChanged();
-            });
-            updateActivityLockScreenState(showing);
         }
+        updateInputRestrictedLocked();
+        mUiOffloadThread.submit(() -> {
+            mTrustManager.reportKeyguardShowingChanged();
+        });
     }
 
     private void notifyTrustedChangedLocked(boolean trusted) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
index d42b87b..142aab2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
@@ -22,6 +22,7 @@
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.RelativeLayout;
+import android.widget.TextView;
 
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
@@ -44,6 +45,7 @@
     private UserInfoController mUserInfoController;
 
     private MultiUserSwitch mMultiUserSwitch;
+    private TextView mUserName;
     private ImageView mMultiUserAvatar;
     private UserGridView mUserGridView;
 
@@ -56,6 +58,7 @@
         super.onFinishInflate();
         mMultiUserSwitch = findViewById(R.id.multi_user_switch);
         mMultiUserAvatar = mMultiUserSwitch.findViewById(R.id.multi_user_avatar);
+        mUserName = findViewById(R.id.user_name);
 
         mUserInfoController = Dependency.get(UserInfoController.class);
 
@@ -89,6 +92,7 @@
     @Override
     public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
         mMultiUserAvatar.setImageDrawable(picture);
+        mUserName.setText(name);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 6c95a80..5a3081c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -18,6 +18,7 @@
 import android.animation.Animator;
 import android.animation.Animator.AnimatorListener;
 import android.animation.AnimatorListenerAdapter;
+import android.app.AlertDialog;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.drawable.Drawable;
@@ -35,6 +36,8 @@
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
 import android.widget.LinearLayout;
 import android.widget.Toolbar;
 import android.widget.Toolbar.OnMenuItemClickListener;
@@ -48,7 +51,9 @@
 import com.android.systemui.qs.QSContainerImpl;
 import com.android.systemui.qs.QSDetailClipper;
 import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.statusbar.phone.LightBarController;
 import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.KeyguardMonitor.Callback;
 
@@ -67,6 +72,7 @@
     private static final String EXTRA_QS_CUSTOMIZING = "qs_customizing";
 
     private final QSDetailClipper mClipper;
+    private final LightBarController mLightBarController;
 
     private boolean isShown;
     private QSTileHost mHost;
@@ -80,6 +86,7 @@
     private int mX;
     private int mY;
     private boolean mOpening;
+    private boolean mIsShowingNavBackdrop;
 
     public QSCustomizer(Context context, AttributeSet attrs) {
         super(new ContextThemeWrapper(context, R.style.edit_theme), attrs);
@@ -114,6 +121,7 @@
         DefaultItemAnimator animator = new DefaultItemAnimator();
         animator.setMoveDuration(TileAdapter.MOVE_DURATION);
         mRecyclerView.setItemAnimator(animator);
+        mLightBarController = Dependency.get(LightBarController.class);
         updateNavBackDrop(getResources().getConfiguration());
     }
 
@@ -125,11 +133,16 @@
 
     private void updateNavBackDrop(Configuration newConfig) {
         View navBackdrop = findViewById(R.id.nav_bar_background);
+        mIsShowingNavBackdrop = newConfig.smallestScreenWidthDp >= 600
+                || newConfig.orientation != Configuration.ORIENTATION_LANDSCAPE;
         if (navBackdrop != null) {
-            boolean shouldShow = newConfig.smallestScreenWidthDp >= 600
-                    || newConfig.orientation != Configuration.ORIENTATION_LANDSCAPE;
-            navBackdrop.setVisibility(shouldShow ? View.VISIBLE : View.GONE);
+            navBackdrop.setVisibility(mIsShowingNavBackdrop ? View.VISIBLE : View.GONE);
         }
+        updateNavColors();
+    }
+
+    private void updateNavColors() {
+        mLightBarController.setQsCustomizing(mIsShowingNavBackdrop && isShown);
     }
 
     public void setHost(QSTileHost host) {
@@ -161,6 +174,7 @@
             announceForAccessibility(mContext.getString(
                     R.string.accessibility_desc_quick_settings_edit));
             Dependency.get(KeyguardMonitor.class).addCallback(mKeyguardCallback);
+            updateNavColors();
         }
     }
 
@@ -176,6 +190,7 @@
             mNotifQsContainer.setCustomizerAnimating(false);
             mNotifQsContainer.setCustomizerShowing(true);
             Dependency.get(KeyguardMonitor.class).addCallback(mKeyguardCallback);
+            updateNavColors();
         }
     }
 
@@ -201,6 +216,7 @@
             announceForAccessibility(mContext.getString(
                     R.string.accessibility_desc_quick_settings));
             Dependency.get(KeyguardMonitor.class).removeCallback(mKeyguardCallback);
+            updateNavColors();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 017365f..176112b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -31,6 +31,7 @@
 import android.service.quicksettings.IQSTileService;
 import android.service.quicksettings.Tile;
 import android.service.quicksettings.TileService;
+import android.text.format.DateUtils;
 import android.util.Log;
 import android.view.IWindowManager;
 import android.view.WindowManagerGlobal;
@@ -51,6 +52,8 @@
 public class CustomTile extends QSTileImpl<State> implements TileChangeListener {
     public static final String PREFIX = "custom(";
 
+    private static final long CUSTOM_STALE_TIMEOUT = DateUtils.HOUR_IN_MILLIS;
+
     private static final boolean DEBUG = false;
 
     // We don't want to thrash binding and unbinding if the user opens and closes the panel a lot.
@@ -83,6 +86,11 @@
         mUser = ActivityManager.getCurrentUser();
     }
 
+    @Override
+    protected long getStaleTimeout() {
+        return CUSTOM_STALE_TIMEOUT + DateUtils.MINUTE_IN_MILLIS * mHost.indexOf(getTileSpec());
+    }
+
     private void setTileIcon() {
         try {
             PackageManager pm = mContext.getPackageManager();
@@ -186,7 +194,7 @@
     }
 
     @Override
-    public void setListening(boolean listening) {
+    public void handleSetListening(boolean listening) {
         if (mListening == listening) return;
         mListening = listening;
         try {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 8c04daf..6a5530f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -32,10 +32,12 @@
 import android.os.Looper;
 import android.os.Message;
 import android.service.quicksettings.Tile;
+import android.text.format.DateUtils;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.SparseArray;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.settingslib.RestrictedLockUtils;
 import com.android.settingslib.Utils;
@@ -45,7 +47,6 @@
 import com.android.systemui.plugins.qs.QSIconView;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTile.State;
-import com.android.systemui.qs.PagedTileLayout;
 import com.android.systemui.qs.PagedTileLayout.TilePage;
 import com.android.systemui.qs.QSHost;
 
@@ -62,14 +63,18 @@
     protected final String TAG = "Tile." + getClass().getSimpleName();
     protected static final boolean DEBUG = Log.isLoggable("Tile", Log.DEBUG);
 
+    private static final long DEFAULT_STALE_TIMEOUT = 10 * DateUtils.MINUTE_IN_MILLIS;
+
     protected final QSHost mHost;
     protected final Context mContext;
-    protected final H mHandler = new H(Dependency.get(Dependency.BG_LOOPER));
+    // @NonFinalForTesting
+    protected H mHandler = new H(Dependency.get(Dependency.BG_LOOPER));
     protected final Handler mUiHandler = new Handler(Looper.getMainLooper());
     private final ArraySet<Object> mListeners = new ArraySet<>();
     private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
 
     private final ArrayList<Callback> mCallbacks = new ArrayList<>();
+    private final Object mStaleListener = new Object();
     protected TState mState = newTileState();
     private TState mTmpState = newTileState();
     private boolean mAnnounceNextStateChange;
@@ -95,6 +100,7 @@
     protected QSTileImpl(QSHost host) {
         mHost = host;
         mContext = host.getContext();
+        handleStale(); // Tile was just created, must be stale.
     }
 
     /**
@@ -106,6 +112,7 @@
             if (mListeners.add(listener) && mListeners.size() == 1) {
                 if (DEBUG) Log.d(TAG, "setListening " + true);
                 mHandler.obtainMessage(H.SET_LISTENING, 1, 0).sendToTarget();
+                refreshState(); // Ensure we get at least one refresh after listening.
             }
         } else {
             if (mListeners.remove(listener) && mListeners.size() == 0) {
@@ -115,6 +122,15 @@
         }
     }
 
+    protected long getStaleTimeout() {
+        return DEFAULT_STALE_TIMEOUT;
+    }
+
+    @VisibleForTesting
+    protected void handleStale() {
+        setListening(mStaleListener, true);
+    }
+
     public String getTileSpec() {
         return mTileSpec;
     }
@@ -273,6 +289,9 @@
         if (changed) {
             handleStateChanged();
         }
+        mHandler.removeMessages(H.STALE);
+        mHandler.sendEmptyMessageDelayed(H.STALE, getStaleTimeout());
+        setListening(mStaleListener, false);
     }
 
     private void handleStateChanged() {
@@ -326,11 +345,11 @@
         handleRefreshState(null);
     }
 
-    protected abstract void setListening(boolean listening);
+    protected abstract void handleSetListening(boolean listening);
 
     protected void handleDestroy() {
         if (mListeners.size() != 0) {
-            setListening(false);
+            handleSetListening(false);
         }
         mCallbacks.clear();
     }
@@ -380,8 +399,10 @@
         private static final int REMOVE_CALLBACKS = 12;
         private static final int REMOVE_CALLBACK = 13;
         private static final int SET_LISTENING = 14;
+        private static final int STALE = 15;
 
-        private H(Looper looper) {
+        @VisibleForTesting
+        protected H(Looper looper) {
             super(looper);
         }
 
@@ -436,8 +457,11 @@
                     name = "handleClearState";
                     handleClearState();
                 } else if (msg.what == SET_LISTENING) {
-                    name = "setListening";
-                    setListening(msg.arg1 != 0);
+                    name = "handleSetListening";
+                    handleSetListening(msg.arg1 != 0);
+                } else if (msg.what == STALE) {
+                    name = "handleStale";
+                    handleStale();
                 } else {
                     throw new IllegalArgumentException("Unknown msg: " + msg.what);
                 }
@@ -515,7 +539,7 @@
         }
     }
 
-    protected class AnimationIcon extends ResourceIcon {
+    protected static class AnimationIcon extends ResourceIcon {
         private final int mAnimatedResId;
 
         public AnimationIcon(int resId, int staticResId) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java
index 13912fe..97e9c3d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java
@@ -48,6 +48,7 @@
             mSlash = null;
             super.setImageDrawable(null);
         } else if (mSlash == null) {
+            setImageLevel(drawable.getLevel());
             super.setImageDrawable(drawable);
         } else {
             mSlash.setAnimationEnabled(mAnimationEnabled);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index 2e7012e..bef1aff 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -110,7 +110,7 @@
         }
     }
 
-    public void setListening(boolean listening) {
+    public void handleSetListening(boolean listening) {
         if (mListening == listening) return;
         mListening = listening;
         if (listening) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
index 3f419a8..95504ed 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -55,7 +55,7 @@
     }
 
     @Override
-    public void setListening(boolean listening) {
+    public void handleSetListening(boolean listening) {
         if (listening) {
             mBatteryController.addCallback(this);
         } else {
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 bc6233d..8d62f2a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -76,7 +76,7 @@
     }
 
     @Override
-    public void setListening(boolean listening) {
+    public void handleSetListening(boolean listening) {
         if (listening) {
             mController.addCallback(mCallback);
         } else {
@@ -136,7 +136,9 @@
                     int batteryLevel = lastDevice.getBatteryLevel();
                     if (batteryLevel != BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
                         BluetoothDeviceLayerDrawable drawable = createLayerDrawable(mContext,
-                                R.drawable.ic_qs_bluetooth_connected, batteryLevel);
+                                R.drawable.ic_qs_bluetooth_connected, batteryLevel,
+                                mContext.getResources().getFraction(
+                                        R.fraction.bt_battery_scale_fraction, 1, 1));
                         state.icon = new DrawableIcon(drawable);
                     }
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 2fc9fc7..fb396b9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -91,9 +91,9 @@
     }
 
     @Override
-    public void setListening(boolean listening) {
+    public void handleSetListening(boolean listening) {
         if (mController == null) return;
-        if (DEBUG) Log.d(TAG, "setListening " + listening);
+        if (DEBUG) Log.d(TAG, "handleSetListening " + listening);
         if (listening) {
             mController.addCallback(mCallback);
             mKeyguard.addCallback(mCallback);
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 f900da0..0bb7479 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -92,7 +92,7 @@
     }
 
     @Override
-    public void setListening(boolean listening) {
+    public void handleSetListening(boolean listening) {
         if (listening) {
             mController.addCallback(mSignalCallback);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index 40fe484..b93f1c2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -63,7 +63,7 @@
     }
 
     @Override
-    public void setListening(boolean listening) {
+    public void handleSetListening(boolean listening) {
         mSetting.setListening(listening);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
index 8b62beb..a102696 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -45,7 +45,7 @@
     }
 
     @Override
-    public void setListening(boolean listening) {
+    public void handleSetListening(boolean listening) {
         if (listening) {
             mDataSaverController.addCallback(this);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 5938749..9e265e22 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -232,7 +232,7 @@
     }
 
     @Override
-    public void setListening(boolean listening) {
+    public void handleSetListening(boolean listening) {
         if (mListening == listening) return;
         mListening = listening;
         if (mListening) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index e6ac908..f2ead1c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -54,7 +54,7 @@
     }
 
     @Override
-    public void setListening(boolean listening) {
+    public void handleSetListening(boolean listening) {
         if (listening) {
             mFlashlightController.addCallback(this);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index c17573d..910b6b1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -74,7 +74,7 @@
     }
 
     @Override
-    public void setListening(boolean listening) {
+    public void handleSetListening(boolean listening) {
         if (mListening == listening) return;
         mListening = listening;
         if (listening) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index 00cfbfa..4f4004c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -76,7 +76,7 @@
     }
 
     @Override
-    public void setListening(boolean listening) {
+    public void handleSetListening(boolean listening) {
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index 5e66334..c35f591 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -55,7 +55,7 @@
     }
 
     @Override
-    public void setListening(boolean listening) {
+    public void handleSetListening(boolean listening) {
         if (listening) {
             mController.addCallback(mCallback);
             mKeyguard.addCallback(mCallback);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
index 6500740..b3ff4e5b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
@@ -51,7 +51,7 @@
     }
 
     @Override
-    public void setListening(boolean listening) {
+    public void handleSetListening(boolean listening) {
         mListening = listening;
         if (mListening) {
             mContext.registerReceiver(mNfcReceiver,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
index 2a12769..4c20361 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -95,7 +95,7 @@
     }
 
     @Override
-    protected void setListening(boolean listening) {
+    protected void handleSetListening(boolean listening) {
         mIsListening = listening;
         if (listening) {
             mController.setListener(this);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index fb937bd..1e00894 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -62,7 +62,7 @@
         return new BooleanState();
     }
 
-    public void setListening(boolean listening) {
+    public void handleSetListening(boolean listening) {
         if (mController == null) return;
         if (listening) {
             mController.addCallback(mCallback);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
index d6043f4..bde1c98 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
@@ -69,7 +69,7 @@
     }
 
     @Override
-    public void setListening(boolean listening) {
+    public void handleSetListening(boolean listening) {
         if (listening) {
             mUserInfoController.addCallback(this);
         } else {
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 136cf21..33b1512 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -75,7 +75,7 @@
     }
 
     @Override
-    public void setListening(boolean listening) {
+    public void handleSetListening(boolean listening) {
         if (listening) {
             mController.addCallback(mSignalCallback);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index 38821f6..5f7d6fb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -48,7 +48,7 @@
     }
 
     @Override
-    public void setListening(boolean listening) {
+    public void handleSetListening(boolean listening) {
         if (listening) {
             mProfileController.addCallback(this);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 3e1522d..406bcac 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -567,9 +567,11 @@
 
     @Override
     public void appTransitionFinished() {
-        // Fallback, reset the flag once an app transition ends
-        EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(
-                false /* waitingForTransitionStart */));
+        if (!Recents.getConfiguration().isLowRamDevice) {
+            // Fallback, reset the flag once an app transition ends
+            EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(
+                    false /* waitingForTransitionStart */));
+        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index f844866..f545556 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -65,6 +65,7 @@
 import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
 import com.android.systemui.recents.events.activity.LaunchTaskSucceededEvent;
 import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
+import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
 import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
 import com.android.systemui.recents.events.component.ActivityUnpinnedEvent;
 import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
@@ -119,6 +120,7 @@
     private boolean mFinishedOnStartup;
     private boolean mIgnoreAltTabRelease;
     private boolean mIsVisible;
+    private boolean mRecentsStartRequested;
     private Configuration mLastConfig;
 
     // Top level views
@@ -416,6 +418,7 @@
             launchState.launchedFromHome = false;
             onEnterAnimationComplete();
         }
+        mRecentsStartRequested = false;
     }
 
     @Override
@@ -449,7 +452,6 @@
      * Reloads the stack views upon launching Recents.
      */
     private void reloadStackView() {
-
         // If the Recents component has preloaded a load plan, then use that to prevent
         // reconstructing the task stack
         RecentsTaskLoader loader = Recents.getTaskLoader();
@@ -572,7 +574,9 @@
         MetricsLogger.hidden(this, MetricsEvent.OVERVIEW_ACTIVITY);
         Recents.getTaskLoader().getHighResThumbnailLoader().setVisible(false);
 
-        if (!isChangingConfigurations()) {
+        // When recents starts again before onStop, do not reset launch flags so entrance animation
+        // can run
+        if (!isChangingConfigurations() && !mRecentsStartRequested) {
             // Workaround for b/22542869, if the RecentsActivity is started again, but without going
             // through SystemUI, we need to reset the config launch flags to ensure that we do not
             // wait on the system to send a signal that was never queued.
@@ -718,6 +722,10 @@
         MetricsLogger.action(this, MetricsEvent.ACTION_OVERVIEW_PAGE);
     }
 
+    public final void onBusEvent(RecentsActivityStartingEvent event) {
+        mRecentsStartRequested = true;
+    }
+
     public final void onBusEvent(UserInteractionEvent event) {
         // Stop the fast-toggle dozer
         mIterateTrigger.stopDozing();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 71f06cb..c44cd72 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -205,6 +205,10 @@
                         mStackButtonShadowDistance.x, mStackButtonShadowDistance.y,
                         mStackButtonShadowColor);
             }
+            if (Recents.getConfiguration().isLowRamDevice) {
+                int bgColor = Utils.getColorAttr(mContext, R.attr.clearAllBackgroundColor);
+                mStackActionButton.setBackgroundColor(bgColor);
+            }
         }
 
         // Let's also require dark status and nav bars if the text is dark
@@ -955,8 +959,8 @@
         int left, top;
         if (Recents.getConfiguration().isLowRamDevice) {
             Rect windowRect = Recents.getSystemServices().getWindowRect();
-            left = (windowRect.width() - mSystemInsets.left - mSystemInsets.right
-                    - mStackActionButton.getMeasuredWidth()) / 2;
+            int spaceLeft = windowRect.width() - mSystemInsets.left - mSystemInsets.right;
+            left = (spaceLeft - mStackActionButton.getMeasuredWidth()) / 2 + mSystemInsets.left;
             top = windowRect.height() - (mStackActionButton.getMeasuredHeight()
                     + mSystemInsets.bottom + mStackActionButton.getPaddingBottom() / 2);
         } else {
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 a633a3e..8899e30 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -2396,10 +2396,14 @@
     }
 
     private void updateStackActionButtonVisibility() {
+        if (Recents.getConfiguration().isLowRamDevice) {
+            return;
+        }
+
         // Always show the button in grid layout.
         if (useGridLayout() ||
                 (mStackScroller.getStackScroll() < SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD &&
-                        mStack.getTaskCount() > 0 && !Recents.getConfiguration().isLowRamDevice)) {
+                        mStack.getTaskCount() > 0)) {
             EventBus.getDefault().send(new ShowStackActionButtonEvent(false /* translate */));
         } else {
             EventBus.getDefault().send(new HideStackActionButtonEvent());
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/lowram/TaskStackLowRamLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/lowram/TaskStackLowRamLayoutAlgorithm.java
index 52fa7b5..17e6b9e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/lowram/TaskStackLowRamLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/lowram/TaskStackLowRamLayoutAlgorithm.java
@@ -126,7 +126,6 @@
             return transformOut;
         }
         boolean visible = true;
-        int x = mPaddingLeftRight;
         int y;
         if (taskCount > 1) {
             y = getTaskTopFromIndex(taskIndex) - percentageToScroll(stackScroll);
@@ -255,7 +254,7 @@
         transformOut.dimAlpha = 0f;
         transformOut.viewOutlineAlpha = 1f;
         transformOut.rect.set(getTaskRect());
-        transformOut.rect.offset(mPaddingLeftRight, y);
+        transformOut.rect.offset(mPaddingLeftRight + mSystemInsets.left, y);
         Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale);
         transformOut.visible = visible;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index a35310f..991c3c8 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -16,11 +16,16 @@
 
 package com.android.systemui.screenshot;
 
+import static com.android.systemui.screenshot.GlobalScreenshot.SHARING_INTENT;
+import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_SCREENSHOT;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
 import android.app.admin.DevicePolicyManager;
 import android.app.Notification;
 import android.app.Notification.BigPictureStyle;
@@ -48,6 +53,7 @@
 import android.os.Environment;
 import android.os.PowerManager;
 import android.os.Process;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.MediaStore;
 import android.util.DisplayMetrics;
@@ -277,14 +283,13 @@
             sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
             sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
 
-            // Create a share action for the notification
-            PendingIntent chooseAction = PendingIntent.getBroadcast(context, 0,
-                    new Intent(context, GlobalScreenshot.TargetChosenReceiver.class),
-                    PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
-            Intent chooserIntent = Intent.createChooser(sharingIntent, null,
-                    chooseAction.getIntentSender())
-                    .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
-            PendingIntent shareAction = PendingIntent.getActivity(context, 0, chooserIntent,
+            // Create a share action for the notification. Note, we proxy the call to ShareReceiver
+            // because RemoteViews currently forces an activity options on the PendingIntent being
+            // launched, and since we don't want to trigger the share sheet in this case, we will
+            // start the chooser activitiy directly in ShareReceiver.
+            PendingIntent shareAction = PendingIntent.getBroadcast(context, 0,
+                    new Intent(context, GlobalScreenshot.ShareReceiver.class)
+                            .putExtra(SHARING_INTENT, sharingIntent),
                     PendingIntent.FLAG_CANCEL_CURRENT);
             Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
                     R.drawable.ic_screenshot_share,
@@ -292,7 +297,7 @@
             mNotificationBuilder.addAction(shareActionBuilder.build());
 
             // Create a delete action for the notification
-            PendingIntent deleteAction = PendingIntent.getBroadcast(context,  0,
+            PendingIntent deleteAction = PendingIntent.getBroadcast(context, 0,
                     new Intent(context, GlobalScreenshot.DeleteScreenshotReceiver.class)
                             .putExtra(GlobalScreenshot.SCREENSHOT_URI_ID, uri.toString()),
                     PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
@@ -403,6 +408,7 @@
 
 class GlobalScreenshot {
     static final String SCREENSHOT_URI_ID = "android:screenshot_uri_id";
+    static final String SHARING_INTENT = "android:screenshot_sharing_intent";
 
     private static final int SCREENSHOT_FLASH_TO_PEAK_DURATION = 130;
     private static final int SCREENSHOT_DROP_IN_DURATION = 430;
@@ -897,6 +903,30 @@
     }
 
     /**
+     * Receiver to proxy the share intent.
+     */
+    public static class ShareReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            try {
+                ActivityManager.getService().closeSystemDialogs(SYSTEM_DIALOG_REASON_SCREENSHOT);
+            } catch (RemoteException e) {
+            }
+
+            Intent sharingIntent = intent.getParcelableExtra(SHARING_INTENT);
+            PendingIntent chooseAction = PendingIntent.getBroadcast(context, 0,
+                    new Intent(context, GlobalScreenshot.TargetChosenReceiver.class),
+                    PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
+            Intent chooserIntent = Intent.createChooser(sharingIntent, null,
+                    chooseAction.getIntentSender())
+                    .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
+            ActivityOptions opts = ActivityOptions.makeBasic();
+            opts.setDisallowEnterPictureInPictureWhileLaunching(true);
+            context.startActivityAsUser(chooserIntent, opts.toBundle(), UserHandle.CURRENT);
+        }
+    }
+
+    /**
      * Removes the notification for a screenshot after a share target is chosen.
      */
     public static class TargetChosenReceiver extends BroadcastReceiver {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index bf98a83..6bfef20 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -66,9 +66,7 @@
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
 import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
-import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
 import com.android.systemui.recents.events.activity.UndockingTaskEvent;
-import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
 import com.android.systemui.recents.events.ui.RecentsGrowingEvent;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.stackdivider.events.StartedDragingEvent;
@@ -124,7 +122,7 @@
     private int mTouchSlop;
     private boolean mBackgroundLifted;
     private boolean mIsInMinimizeInteraction;
-    private int mDividerPositionBeforeMinimized;
+    private SnapTarget mSnapTargetBeforeMinimized;
 
     private int mDividerInsets;
     private int mDisplayWidth;
@@ -318,6 +316,12 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         EventBus.getDefault().register(this);
+
+        // Save the current target if not minimized once attached to window
+        if (mHomeStackResizable && mDockSide != WindowManager.DOCKED_INVALID
+                && !mIsInMinimizeInteraction) {
+            saveSnapTargetBeforeMinimized(mSnapTargetBeforeMinimized);
+        }
     }
 
     @Override
@@ -381,8 +385,10 @@
                 (isHorizontalDivision() ? mDisplayHeight : mDisplayWidth));
         mSnapAlgorithm = null;
         initializeSnapAlgorithm();
-        mDividerPositionBeforeMinimized = mSnapAlgorithm.calculateNonDismissingSnapTarget(position)
-                .position;
+
+        // Set the snap target before minimized but do not save until divider is attached and not
+        // minimized because it does not know its minimized state yet.
+        mSnapTargetBeforeMinimized = mSnapAlgorithm.calculateNonDismissingSnapTarget(position);
     }
 
     public WindowManagerProxy getWindowManagerProxy() {
@@ -601,6 +607,11 @@
             mEntranceAnimationRunning = false;
             mExitAnimationRunning = false;
             EventBus.getDefault().send(new StoppedDragingEvent());
+
+            // Record last snap target the divider moved to
+            if (mHomeStackResizable && !mIsInMinimizeInteraction) {
+                saveSnapTargetBeforeMinimized(snapTarget);
+            }
         };
         Runnable notCancelledEndAction = () -> {
             // Reset minimized divider position after unminimized state animation finishes
@@ -629,15 +640,15 @@
                     delay = mSfChoreographer.getSurfaceFlingerOffsetMs();
                 }
                 if (delay == 0) {
-                    endAction.run();
                     if (!mCancelled) {
                         notCancelledEndAction.run();
                     }
+                    endAction.run();
                 } else {
-                    mHandler.postDelayed(endAction, delay);
                     if (!mCancelled) {
                         mHandler.postDelayed(notCancelledEndAction, delay);
                     }
+                    mHandler.postDelayed(endAction, delay);
                 }
             }
         });
@@ -744,12 +755,9 @@
             if (mIsInMinimizeInteraction != minimized) {
                 if (minimized) {
                     mIsInMinimizeInteraction = true;
-                    int position = mMinimizedSnapAlgorithm.getMiddleTarget().position;
-                    resizeStack(position, position, mMinimizedSnapAlgorithm.getMiddleTarget());
+                    resizeStack(mMinimizedSnapAlgorithm.getMiddleTarget());
                 } else {
-                    resizeStack(mDividerPositionBeforeMinimized, mDividerPositionBeforeMinimized,
-                            mSnapAlgorithm.calculateNonDismissingSnapTarget(
-                                    mDividerPositionBeforeMinimized));
+                    resizeStack(mSnapTargetBeforeMinimized);
                     mIsInMinimizeInteraction = false;
                 }
             }
@@ -786,20 +794,15 @@
             mDockedStackMinimized = minimized;
         } else if (mDockedStackMinimized != minimized) {
             mIsInMinimizeInteraction = true;
-            if (minimized && (mCurrentAnimator == null || !mCurrentAnimator.isRunning())
-                    && (mDividerPositionBeforeMinimized <= 0 || !mAdjustedForIme)) {
-                savePositionBeforeMinimized();
-            }
             mMinimizedSnapAlgorithm = null;
             mDockedStackMinimized = minimized;
             initializeSnapAlgorithm();
             stopDragging(minimized
-                            ? mDividerPositionBeforeMinimized
+                            ? mSnapTargetBeforeMinimized.position
                             : getCurrentPosition(),
                     minimized
                             ? mMinimizedSnapAlgorithm.getMiddleTarget()
-                            : mSnapAlgorithm.calculateNonDismissingSnapTarget(
-                                    mDividerPositionBeforeMinimized),
+                            : mSnapTargetBeforeMinimized,
                     animDuration, Interpolators.FAST_OUT_SLOW_IN, 0);
             setAdjustedForIme(false, animDuration);
         }
@@ -844,17 +847,11 @@
                 .setDuration(animDuration)
                 .start();
         mAdjustedForIme = adjustedForIme;
-
-        // Only get new position if home stack is resizable, ime is open and not minimized
-        // (including the animation)
-        if (mHomeStackResizable && adjustedForIme && !mIsInMinimizeInteraction) {
-            savePositionBeforeMinimized();
-        }
     }
 
-    private void savePositionBeforeMinimized() {
-        mDividerPositionBeforeMinimized = getCurrentPosition();
-        mState.mRatioPositionBeforeMinimized = (float) mDividerPositionBeforeMinimized /
+    private void saveSnapTargetBeforeMinimized(SnapTarget target) {
+        mSnapTargetBeforeMinimized = target;
+        mState.mRatioPositionBeforeMinimized = (float) target.position /
                 (isHorizontalDivision() ? mDisplayHeight : mDisplayWidth);
     }
 
@@ -872,7 +869,6 @@
         updateDisplayInfo();
     }
 
-
     public void notifyDockSideChanged(int newDockSide) {
         mDockSide = newDockSide;
         mMinimizedShadow.setDockSide(mDockSide);
@@ -934,6 +930,10 @@
         mSfChoreographer.scheduleAtSfVsync(mHandler, message);
     }
 
+    private void resizeStack(SnapTarget taskSnapTarget) {
+        resizeStack(taskSnapTarget.position, taskSnapTarget.position, taskSnapTarget);
+    }
+
     public void resizeStack(int position, int taskPosition, SnapTarget taskSnapTarget) {
         if (mRemoved) {
             // This divider view has been removed so shouldn't have any additional influence.
@@ -952,8 +952,9 @@
 
         mLastResizeRect.set(mDockedRect);
         if (mHomeStackResizable && mIsInMinimizeInteraction) {
-            calculateBoundsForPosition(mDividerPositionBeforeMinimized, mDockSide, mDockedTaskRect);
-            calculateBoundsForPosition(mDividerPositionBeforeMinimized,
+            calculateBoundsForPosition(mSnapTargetBeforeMinimized.position, mDockSide,
+                    mDockedTaskRect);
+            calculateBoundsForPosition(mSnapTargetBeforeMinimized.position,
                     DockedDividerUtils.invertDockSide(mDockSide), mOtherTaskRect);
             mWindowManagerProxy.resizeDockedStack(mDockedRect, mDockedTaskRect, mDockedTaskRect,
                     mOtherTaskRect, null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 7bc1a39..8fa904e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -64,10 +64,10 @@
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
 import com.android.systemui.statusbar.NotificationGuts.GutsContent;
 import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
-import com.android.systemui.statusbar.notification.AboveShelfObserver;
 import com.android.systemui.statusbar.notification.HybridNotificationView;
 import com.android.systemui.statusbar.notification.NotificationInflater;
 import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.notification.NotificationViewWrapper;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.StatusBar;
@@ -80,6 +80,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.function.BooleanSupplier;
 
 public class ExpandableNotificationRow extends ActivatableNotificationView
         implements PluginListener<NotificationMenuRowPlugin> {
@@ -93,6 +94,7 @@
     }
 
     private LayoutListener mLayoutListener;
+    private boolean mDark;
     private boolean mLowPriorityStateUpdated;
     private final NotificationInflater mNotificationInflater;
     private int mIconTransformContentShift;
@@ -175,6 +177,11 @@
     private boolean mGroupExpansionChanging;
 
     /**
+     * A supplier that returns true if keyguard is secure.
+     */
+    private BooleanSupplier mSecureStateProvider;
+
+    /**
      * Whether or not a notification that is not part of a group of notifications can be manually
      * expanded by the user.
      */
@@ -395,6 +402,14 @@
         mAboveShelfChangedListener = aboveShelfChangedListener;
     }
 
+    /**
+     * Sets a supplier that can determine whether the keyguard is secure or not.
+     * @param secureStateProvider A function that returns true if keyguard is secure.
+     */
+    public void setSecureStateProvider(BooleanSupplier secureStateProvider) {
+        mSecureStateProvider = secureStateProvider;
+    }
+
     @Override
     public boolean isDimmable() {
         if (!getShowingLayout().isDimmable()) {
@@ -421,6 +436,9 @@
         } else {
             minHeight = mNotificationMinHeight;
         }
+        NotificationViewWrapper collapsedWrapper = layout.getVisibleWrapper(
+                NotificationContentView.VISIBLE_TYPE_CONTRACTED);
+        minHeight += collapsedWrapper.getMinHeightIncrease(mUseIncreasedCollapsedHeight);
         boolean headsUpCustom = layout.getHeadsUpChild() != null &&
                 layout.getHeadsUpChild().getId()
                         != com.android.internal.R.id.status_bar_latest_event_content;
@@ -432,6 +450,11 @@
         } else {
             headsUpheight = mMaxHeadsUpHeight;
         }
+        NotificationViewWrapper headsUpWrapper = layout.getVisibleWrapper(
+                NotificationContentView.VISIBLE_TYPE_HEADSUP);
+        if (headsUpWrapper != null) {
+            headsUpheight += headsUpWrapper.getMinHeightIncrease(mUseIncreasedCollapsedHeight);
+        }
         layout.setHeights(minHeight, headsUpheight, mNotificationMaxHeight,
                 mNotificationAmbientHeight);
     }
@@ -1454,6 +1477,7 @@
     @Override
     public void setDark(boolean dark, boolean fade, long delay) {
         super.setDark(dark, fade, delay);
+        mDark = dark;
         if (!mIsHeadsUp) {
             // Only fade the showing view of the pulsing notification.
             fade = false;
@@ -1468,6 +1492,17 @@
         updateShelfIconColor();
     }
 
+    /**
+     * Tap sounds should not be played when we're unlocking.
+     * Doing so would cause audio collision and the system would feel unpolished.
+     */
+    @Override
+    public boolean isSoundEffectsEnabled() {
+        final boolean mute = mDark && mSecureStateProvider != null &&
+                !mSecureStateProvider.getAsBoolean();
+        return !mute && super.isSoundEffectsEnabled();
+    }
+
     public boolean isExpandable() {
         if (mIsSummaryWithChildren && !mShowingPublic) {
             return !mChildrenExpanded;
@@ -1989,14 +2024,15 @@
     }
 
     @Override
-    public int getMinHeight() {
-        if (mGuts != null && mGuts.isExposed()) {
+    public int getMinHeight(boolean ignoreTemporaryStates) {
+        if (!ignoreTemporaryStates && mGuts != null && mGuts.isExposed()) {
             return mGuts.getIntrinsicHeight();
-        } else if (isHeadsUpAllowed() && mIsHeadsUp && mHeadsUpManager.isTrackingHeadsUp()) {
+        } else if (!ignoreTemporaryStates && isHeadsUpAllowed() && mIsHeadsUp
+                && mHeadsUpManager.isTrackingHeadsUp()) {
                 return getPinnedHeadsUpHeight(false /* atLeastMinHeight */);
         } else if (mIsSummaryWithChildren && !isGroupExpanded() && !mShowingPublic) {
             return mChildrenContainer.getMinHeight();
-        } else if (isHeadsUpAllowed() && mIsHeadsUp) {
+        } else if (!ignoreTemporaryStates && isHeadsUpAllowed() && mIsHeadsUp) {
             return mHeadsUpHeight;
         }
         NotificationContentView showingLayout = getShowingLayout();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index efe5e0c..aac9af8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -151,9 +151,21 @@
     }
 
     /**
-     * @return The minimum content height of this notification.
+     * @return The minimum content height of this notification. This also respects the temporary
+     * states of the view.
      */
     public int getMinHeight() {
+        return getMinHeight(false /* ignoreTemporaryStates */);
+    }
+
+    /**
+     * Get the minimum height of this view.
+     *
+     * @param ignoreTemporaryStates should temporary states be ignored like the guts or heads-up.
+     *
+     * @return The minimum height that this view needs.
+     */
+    public int getMinHeight(boolean ignoreTemporaryStates) {
         return getHeight();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index ddc7dd0..d0417b5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -292,8 +292,8 @@
 
             if (mRankingMap != null) {
                 // RankingMap as received from NoMan
-                mRankingMap.getRanking(a.key, mRankingA);
-                mRankingMap.getRanking(b.key, mRankingB);
+                getRanking(a.key, mRankingA);
+                getRanking(b.key, mRankingB);
                 aImportance = mRankingA.getImportance();
                 bImportance = mRankingB.getImportance();
                 aRank = mRankingA.getRank();
@@ -381,7 +381,7 @@
 
     public boolean isAmbient(String key) {
         if (mRankingMap != null) {
-            mRankingMap.getRanking(key, mTmpRanking);
+            getRanking(key, mTmpRanking);
             return mTmpRanking.isAmbient();
         }
         return false;
@@ -389,7 +389,7 @@
 
     public int getVisibilityOverride(String key) {
         if (mRankingMap != null) {
-            mRankingMap.getRanking(key, mTmpRanking);
+            getRanking(key, mTmpRanking);
             return mTmpRanking.getVisibilityOverride();
         }
         return Ranking.VISIBILITY_NO_OVERRIDE;
@@ -397,7 +397,7 @@
 
     public boolean shouldSuppressScreenOff(String key) {
         if (mRankingMap != null) {
-            mRankingMap.getRanking(key, mTmpRanking);
+            getRanking(key, mTmpRanking);
             return (mTmpRanking.getSuppressedVisualEffects()
                     & NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_OFF) != 0;
         }
@@ -406,7 +406,7 @@
 
     public boolean shouldSuppressScreenOn(String key) {
         if (mRankingMap != null) {
-            mRankingMap.getRanking(key, mTmpRanking);
+            getRanking(key, mTmpRanking);
             return (mTmpRanking.getSuppressedVisualEffects()
                     & NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_ON) != 0;
         }
@@ -415,7 +415,7 @@
 
     public int getImportance(String key) {
         if (mRankingMap != null) {
-            mRankingMap.getRanking(key, mTmpRanking);
+            getRanking(key, mTmpRanking);
             return mTmpRanking.getImportance();
         }
         return NotificationManager.IMPORTANCE_UNSPECIFIED;
@@ -423,7 +423,7 @@
 
     public String getOverrideGroupKey(String key) {
         if (mRankingMap != null) {
-            mRankingMap.getRanking(key, mTmpRanking);
+            getRanking(key, mTmpRanking);
             return mTmpRanking.getOverrideGroupKey();
         }
          return null;
@@ -431,7 +431,7 @@
 
     public List<SnoozeCriterion> getSnoozeCriteria(String key) {
         if (mRankingMap != null) {
-            mRankingMap.getRanking(key, mTmpRanking);
+            getRanking(key, mTmpRanking);
             return mTmpRanking.getSnoozeCriteria();
         }
         return null;
@@ -439,7 +439,7 @@
 
     public NotificationChannel getChannel(String key) {
         if (mRankingMap != null) {
-            mRankingMap.getRanking(key, mTmpRanking);
+            getRanking(key, mTmpRanking);
             return mTmpRanking.getChannel();
         }
         return null;
@@ -452,6 +452,9 @@
                 final int N = mEntries.size();
                 for (int i = 0; i < N; i++) {
                     Entry entry = mEntries.valueAt(i);
+                    if (!getRanking(entry.key, mTmpRanking)) {
+                        continue;
+                    }
                     final StatusBarNotification oldSbn = entry.notification.cloneLight();
                     final String overrideGroupKey = getOverrideGroupKey(entry.key);
                     if (!Objects.equals(oldSbn.getOverrideGroupKey(), overrideGroupKey)) {
@@ -466,6 +469,19 @@
         filterAndSort();
     }
 
+    /**
+     * Get the ranking from the current ranking map.
+     *
+     * @param key the key to look up
+     * @param outRanking the ranking to populate
+     *
+     * @return {@code true} if the ranking was properly obtained.
+     */
+    @VisibleForTesting
+    protected boolean getRanking(String key, Ranking outRanking) {
+        return mRankingMap.getRanking(key, outRanking);
+    }
+
     // TODO: This should not be public. Instead the Environment should notify this class when
     // anything changed, and this class should call back the UI so it updates itself.
     public void filterAndSort() {
@@ -573,7 +589,7 @@
     }
 
     private void dumpEntry(PrintWriter pw, String indent, int i, Entry e) {
-        mRankingMap.getRanking(e.key, mTmpRanking);
+        getRanking(e.key, mTmpRanking);
         pw.print(indent);
         pw.println("  [" + i + "] key=" + e.key + " icon=" + e.icon);
         StatusBarNotification n = e.notification;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index 1ffb3b5..3b23a0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -126,7 +126,7 @@
                             | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
                             | PackageManager.MATCH_DIRECT_BOOT_AWARE);
             if (info != null) {
-                mAppUid = info.uid;
+                mAppUid = sbn.getUid();
                 mAppName = String.valueOf(pm.getApplicationLabel(info));
                 pkgicon = pm.getApplicationIcon(info);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 5eefe9a..5557dde 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -22,10 +22,12 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.graphics.Rect;
 import android.os.SystemProperties;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
 import android.view.accessibility.AccessibilityNodeInfo;
 
 import com.android.systemui.Interpolators;
@@ -53,6 +55,7 @@
             SystemProperties.getBoolean("debug.icon_opening_animations", true);
     private static final boolean ICON_ANMATIONS_WHILE_SCROLLING
             = SystemProperties.getBoolean("debug.icon_scroll_animations", true);
+    private static final int TAG_CONTINUOUS_CLIPPING = R.id.continuous_clipping_tag;
     private ViewInvertHelper mViewInvertHelper;
     private boolean mDark;
     private NotificationIconContainer mShelfIcons;
@@ -305,6 +308,16 @@
         mShelfIcons.setSpeedBumpIndex(mAmbientState.getSpeedBumpIndex());
         mShelfIcons.calculateIconTranslations();
         mShelfIcons.applyIconStates();
+        for (int i = 0; i < mHostLayout.getChildCount(); i++) {
+            View child = mHostLayout.getChildAt(i);
+            if (!(child instanceof ExpandableNotificationRow)
+                    || child.getVisibility() == GONE) {
+                continue;
+            }
+            ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+            updateIconClipAmount(row);
+            updateContinuousClipping(row);
+        }
         boolean hideBackground = numViewsInShelf < 1.0f;
         setHideBackground(hideBackground || backgroundForceHidden);
         if (mNotGoneIndex == -1) {
@@ -312,6 +325,43 @@
         }
     }
 
+    private void updateIconClipAmount(ExpandableNotificationRow row) {
+        float maxTop = row.getTranslationY();
+        StatusBarIconView icon = row.getEntry().expandedIcon;
+        float shelfIconPosition = getTranslationY() + icon.getTop() + icon.getTranslationY();
+        if (shelfIconPosition < maxTop) {
+            int top = (int) (maxTop - shelfIconPosition);
+            Rect clipRect = new Rect(0, top, icon.getWidth(), Math.max(top, icon.getHeight()));
+            icon.setClipBounds(clipRect);
+        } else {
+            icon.setClipBounds(null);
+        }
+    }
+
+    private void updateContinuousClipping(final ExpandableNotificationRow row) {
+        StatusBarIconView icon = row.getEntry().expandedIcon;
+        boolean needsContinuousClipping = ViewState.isAnimatingY(icon);
+        boolean isContinuousClipping = icon.getTag(TAG_CONTINUOUS_CLIPPING) != null;
+        if (needsContinuousClipping && !isContinuousClipping) {
+            ViewTreeObserver.OnPreDrawListener predrawListener =
+                    new ViewTreeObserver.OnPreDrawListener() {
+                        @Override
+                        public boolean onPreDraw() {
+                            boolean animatingY = ViewState.isAnimatingY(icon);
+                            if (!animatingY || !icon.isAttachedToWindow()) {
+                                icon.getViewTreeObserver().removeOnPreDrawListener(this);
+                                icon.setTag(TAG_CONTINUOUS_CLIPPING, null);
+                                return true;
+                            }
+                            updateIconClipAmount(row);
+                            return true;
+                        }
+                    };
+            icon.getViewTreeObserver().addOnPreDrawListener(predrawListener);
+            icon.setTag(TAG_CONTINUOUS_CLIPPING, predrawListener);
+        }
+    }
+
     private void updateNotificationClipHeight(ExpandableNotificationRow row,
             float notificationClipEnd) {
         float viewEnd = row.getTranslationY() + row.getActualHeight();
@@ -330,6 +380,15 @@
         }
     }
 
+    @Override
+    public void setFakeShadowIntensity(float shadowIntensity, float outlineAlpha, int shadowYEnd,
+            int outlineTranslation) {
+        if (!mHasItemsInStableShelf) {
+            shadowIntensity = 0.0f;
+        }
+        super.setFakeShadowIntensity(shadowIntensity, outlineAlpha, shadowYEnd, outlineTranslation);
+    }
+
     /**
      * @return the icon amount how much this notification is in the shelf;
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
index fcc982ea..b95b8a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
@@ -114,7 +114,6 @@
         mIcon = mView.findViewById(com.android.internal.R.id.icon);
         mHeaderText = mView.findViewById(com.android.internal.R.id.header_text);
         mExpandButton = mView.findViewById(com.android.internal.R.id.expand_button);
-        mExpandButton.setLabeledBy(mRow);
         mWorkProfileImage = mView.findViewById(com.android.internal.R.id.profile_badge);
         mColor = resolveColor(mExpandButton);
         mNotificationHeader = mView.findViewById(com.android.internal.R.id.notification_header);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
index bb979eb..9bfa7a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
@@ -25,6 +25,7 @@
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
+import com.android.systemui.R;
 import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.TransformableView;
@@ -47,6 +48,7 @@
 
     private int mContentHeight;
     private int mMinHeightHint;
+    private boolean mColorized;
 
     protected NotificationTemplateViewWrapper(Context ctx, View view,
             ExpandableNotificationRow row) {
@@ -162,7 +164,9 @@
     public void onContentUpdated(ExpandableNotificationRow row) {
         // Reinspect the notification. Before the super call, because the super call also updates
         // the transformation types and we need to have our values set by then.
-        resolveTemplateViews(row.getStatusBarNotification());
+        StatusBarNotification sbn = row.getStatusBarNotification();
+        resolveTemplateViews(sbn);
+        mColorized = sbn.getNotification().isColorized();
         super.onContentUpdated(row);
     }
 
@@ -265,6 +269,17 @@
         updateActionOffset();
     }
 
+    @Override
+    public int getMinHeightIncrease(boolean useIncreasedCollapsedHeight) {
+        if (mColorized) {
+            int dimen = useIncreasedCollapsedHeight
+                    ? R.dimen.notification_height_increase_colorized_increased
+                    : R.dimen.notification_height_increase_colorized;
+            return mRow.getResources().getDimensionPixelSize(dimen);
+        }
+        return super.getMinHeightIncrease(useIncreasedCollapsedHeight);
+    }
+
     private void updateActionOffset() {
         if (mActionsContainer != null) {
             // We should never push the actions higher than they are in the headsup view.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
index 5200d69..085bce9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -190,4 +190,14 @@
     public boolean disallowSingleClick(float x, float y) {
         return false;
     }
+
+    /**
+     * Get the amount that the minheight is allowed to be increased based on this layout.
+     *
+     * @param increasedHeight is the view allowed to show even bigger, i.e for messaging layouts
+     * @return
+     */
+    public int getMinHeightIncrease(boolean increasedHeight) {
+        return 0;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index f379a46..4bca797 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -41,8 +41,6 @@
     private static final boolean DEBUG = false;
     private static final boolean DEBUG_COLORS = false;
 
-    public static final boolean HIGH_END = ActivityManager.isHighEndGfx();
-
     public static final int MODE_OPAQUE = 0;
     public static final int MODE_SEMI_TRANSPARENT = 1;
     public static final int MODE_TRANSLUCENT = 2;
@@ -52,7 +50,7 @@
     public static final int MODE_LIGHTS_OUT_TRANSPARENT = 6;
 
     public static final int LIGHTS_IN_DURATION = 250;
-    public static final int LIGHTS_OUT_DURATION = 750;
+    public static final int LIGHTS_OUT_DURATION = 1500;
     public static final int BACKGROUND_DURATION = 200;
 
     private final String mTag;
@@ -66,9 +64,7 @@
         mTag = "BarTransitions." + view.getClass().getSimpleName();
         mView = view;
         mBarBackground = new BarBackgroundDrawable(mView.getContext(), gradientResourceId);
-        if (HIGH_END) {
-            mView.setBackground(mBarBackground);
-        }
+        mView.setBackground(mBarBackground);
     }
 
     public int getMode() {
@@ -89,7 +85,7 @@
 
     public boolean isAlwaysOpaque() {
         // Low-end devices do not support translucent modes, fallback to opaque
-        return !HIGH_END || mAlwaysOpaque;
+        return mAlwaysOpaque;
     }
 
     public void transitionTo(int mode, boolean animate) {
@@ -109,9 +105,7 @@
     }
 
     protected void onTransition(int oldMode, int newMode, boolean animate) {
-        if (HIGH_END) {
-            applyModeBackground(oldMode, newMode, animate);
-        }
+        applyModeBackground(oldMode, newMode, animate);
     }
 
     protected void applyModeBackground(int oldMode, int newMode, boolean animate) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index 8c923cb..2c3f452 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -161,10 +161,6 @@
                 showNotificationIconArea(animate);
             }
         }
-        if (!BarTransitions.HIGH_END) {
-            int mask = DISABLE_NOTIFICATION_ICONS | DISABLE_SYSTEM_INFO;
-            getView().setVisibility((mDisabled1 & mask) == mask ? View.GONE : View.VISIBLE);
-        }
     }
 
     protected int adjustDisableFlags(int state) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
index 316d229..91369db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
@@ -85,6 +85,11 @@
     public static final int MODE_DISMISS_BOUNCER = 6;
 
     /**
+     * Mode in which fingerprint wakes and unlocks the device from a dream.
+     */
+    public static final int MODE_WAKE_AND_UNLOCK_FROM_DREAM = 7;
+
+    /**
      * How much faster we collapse the lockscreen when authenticating with fingerprint.
      */
     private static final float FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR = 1.1f;
@@ -193,6 +198,8 @@
     }
 
     public void startWakeAndUnlock(int mode) {
+        // TODO(b/62444020): remove when this bug is fixed
+        Log.v(TAG, "startWakeAndUnlock(" + mode + ")");
         boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();
         mMode = mode;
         mHasScreenTurnedOnSinceAuthenticating = false;
@@ -230,16 +237,19 @@
                 }
                 Trace.endSection();
                 break;
+            case MODE_WAKE_AND_UNLOCK_FROM_DREAM:
             case MODE_WAKE_AND_UNLOCK_PULSING:
             case MODE_WAKE_AND_UNLOCK:
                 if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {
                     Trace.beginSection("MODE_WAKE_AND_UNLOCK_PULSING");
                     mStatusBar.updateMediaMetaData(false /* metaDataChanged */,
                             true /* allowEnterAnimation */);
-                } else {
+                } else if (mMode == MODE_WAKE_AND_UNLOCK){
                     Trace.beginSection("MODE_WAKE_AND_UNLOCK");
-
                     mDozeScrimController.abortDoze();
+                } else {
+                    Trace.beginSection("MODE_WAKE_AND_UNLOCK_FROM_DREAM");
+                    mUpdateMonitor.awakenFromDream();
                 }
                 mStatusBarWindowManager.setStatusBarFocusable(false);
                 mKeyguardViewMediator.onWakeAndUnlocking();
@@ -299,6 +309,7 @@
 
     private int calculateMode() {
         boolean unlockingAllowed = mUpdateMonitor.isUnlockingWithFingerprintAllowed();
+        boolean deviceDreaming = mUpdateMonitor.isDreaming();
 
         if (!mUpdateMonitor.isDeviceInteractive()) {
             if (!mStatusBarKeyguardViewManager.isShowing()) {
@@ -311,6 +322,9 @@
                 return MODE_SHOW_BOUNCER;
             }
         }
+        if (unlockingAllowed && deviceDreaming) {
+            return MODE_WAKE_AND_UNLOCK_FROM_DREAM;
+        }
         if (mStatusBarKeyguardViewManager.isShowing()) {
             if (mStatusBarKeyguardViewManager.isBouncerShowing() && unlockingAllowed) {
                 return MODE_DISMISS_BOUNCER;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index fd95cc4..99debee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -27,6 +27,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
+import android.view.WindowInsets;
 import android.view.accessibility.AccessibilityEvent;
 
 import com.android.internal.widget.LockPatternUtils;
@@ -69,6 +70,7 @@
                 }
             };
     private final Runnable mRemoveViewRunnable = this::removeView;
+    private int mStatusBarHeight;
 
     public KeyguardBouncer(Context context, ViewMediatorCallback callback,
             LockPatternUtils lockPatternUtils, ViewGroup container,
@@ -128,7 +130,9 @@
             mRoot.setVisibility(View.VISIBLE);
             mKeyguardView.onResume();
             showPromptReason(mBouncerPromptReason);
-            if (mKeyguardView.getHeight() != 0) {
+            // We might still be collapsed and the view didn't have time to layout yet or still
+            // be small, let's wait on the predraw to do the animation in that case.
+            if (mKeyguardView.getHeight() != 0 && mKeyguardView.getHeight() != mStatusBarHeight) {
                 mKeyguardView.startAppearAnimation();
             } else {
                 mKeyguardView.getViewTreeObserver().addOnPreDrawListener(
@@ -247,12 +251,18 @@
         removeView();
         mHandler.removeCallbacks(mRemoveViewRunnable);
         mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
-        mKeyguardView = (KeyguardHostView) mRoot.findViewById(R.id.keyguard_host_view);
+        mKeyguardView = mRoot.findViewById(R.id.keyguard_host_view);
         mKeyguardView.setLockPatternUtils(mLockPatternUtils);
         mKeyguardView.setViewMediatorCallback(mCallback);
         mContainer.addView(mRoot, mContainer.getChildCount());
+        mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset(
+                com.android.systemui.R.dimen.status_bar_height);
         mRoot.setVisibility(View.INVISIBLE);
-        mRoot.dispatchApplyWindowInsets(mRoot.getRootWindowInsets());
+
+        final WindowInsets rootInsets = mRoot.getRootWindowInsets();
+        if (rootInsets != null) {
+            mRoot.dispatchApplyWindowInsets(rootInsets);
+        }
     }
 
     protected void removeView() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index 917a56f..533771a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -72,6 +72,7 @@
 
     private final Rect mLastFullscreenBounds = new Rect();
     private final Rect mLastDockedBounds = new Rect();
+    private boolean mQsCustomizing;
 
     public LightBarController(Context ctx) {
         mDarkModeColor = Color.valueOf(ctx.getColor(R.color.dark_mode_icon_color_single_tone));
@@ -129,7 +130,8 @@
             mHasLightNavigationBar = isLight(vis, navigationBarMode,
                     View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
             mNavigationLight = mHasLightNavigationBar
-                    && (mScrimAlphaBelowThreshold || !mInvertLightNavBarWithScrim);
+                    && (mScrimAlphaBelowThreshold || !mInvertLightNavBarWithScrim)
+                    && !mQsCustomizing;
             if (mNavigationLight != last) {
                 updateNavigation();
             }
@@ -146,6 +148,12 @@
                 mLastNavigationBarMode);
     }
 
+    public void setQsCustomizing(boolean customizing) {
+        if (mQsCustomizing == customizing) return;
+        mQsCustomizing = customizing;
+        reevaluate();
+    }
+
     public void setScrimAlpha(float alpha) {
         mScrimAlpha = alpha;
         boolean belowThresholdBefore = mScrimAlphaBelowThreshold;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index d3a6280..b0ac6ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -127,11 +127,6 @@
     }
 
     public void setIconsDark(boolean dark, boolean animate) {
-        if (!BarTransitions.HIGH_END) {
-            setIconTintInternal(0.0f);
-            mNextDarkIntensity = 0.0f;
-            return;
-        }
         if (!animate) {
             setIconTintInternal(dark ? 1.0f : 0.0f);
             mNextDarkIntensity = dark ? 1.0f : 0.0f;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
index 004a604..1452e0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
@@ -87,7 +87,8 @@
             if (mTouchingChild != null) {
                 event.offsetLocation(mTouchingChild.getWidth() / 2 - event.getX(),
                         mTouchingChild.getHeight() / 2 - event.getY());
-                return mTouchingChild.dispatchTouchEvent(event);
+                return mTouchingChild.getVisibility() == VISIBLE
+                        && mTouchingChild.dispatchTouchEvent(event);
             }
         }
         return super.onTouchEvent(event);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 88a5626..0f246c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -25,10 +25,8 @@
 import android.graphics.Paint;
 import android.graphics.drawable.Icon;
 import android.os.AsyncTask;
-import android.os.UserHandle;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
-import android.provider.Settings;
 import android.support.v4.util.ArrayMap;
 import android.support.v4.util.ArraySet;
 import android.util.AttributeSet;
@@ -39,10 +37,8 @@
 import com.android.systemui.R;
 import com.android.systemui.statusbar.AlphaOptimizedFrameLayout;
 import com.android.systemui.statusbar.StatusBarIconView;
-import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.stack.AnimationFilter;
 import com.android.systemui.statusbar.stack.AnimationProperties;
-import com.android.systemui.statusbar.stack.StackStateAnimator;
 import com.android.systemui.statusbar.stack.ViewState;
 
 import java.util.ArrayList;
@@ -84,7 +80,10 @@
     }.setDuration(CANNED_ANIMATION_DURATION)
             .setCustomInterpolator(View.TRANSLATION_Y, Interpolators.ICON_OVERSHOT);
 
-    private static final AnimationProperties mTempProperties = new AnimationProperties() {
+    /**
+     * Temporary AnimationProperties to avoid unnecessary allocations.
+     */
+    private static final AnimationProperties sTempProperties = new AnimationProperties() {
         private AnimationFilter mAnimationFilter = new AnimationFilter();
 
         @Override
@@ -102,15 +101,6 @@
         }
     }.setDuration(200).setDelay(50);
 
-    private static final AnimationProperties UNDARK_PROPERTIES = new AnimationProperties() {
-        private AnimationFilter mAnimationFilter = new AnimationFilter()
-                .animateX();
-
-        @Override
-        public AnimationFilter getAnimationFilter() {
-            return mAnimationFilter;
-        }
-    }.setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP);
     public static final int MAX_VISIBLE_ICONS_WHEN_DARK = 5;
 
     private boolean mShowAllIcons = true;
@@ -478,9 +468,6 @@
             View view = getChildAt(i);
             if (view instanceof StatusBarIconView) {
                 ((StatusBarIconView) view).setDark(dark, fade, delay);
-                if (!dark && fade) {
-                    getIconState((StatusBarIconView) view).justUndarkened = true;
-                }
             }
         }
     }
@@ -551,7 +538,6 @@
         public boolean useFullTransitionAmount;
         public boolean useLinearTransitionAmount;
         public boolean translateContent;
-        public boolean justUndarkened;
         public int iconColor = StatusBarIconView.NO_COLOR;
         public boolean noAnimations;
         public boolean isLastExpandIcon;
@@ -563,8 +549,7 @@
                 StatusBarIconView icon = (StatusBarIconView) view;
                 boolean animate = false;
                 AnimationProperties animationProperties = null;
-                boolean animationsAllowed = (mAnimationsEnabled || justUndarkened)
-                        && !mDisallowNextAnimation
+                boolean animationsAllowed = mAnimationsEnabled && !mDisallowNextAnimation
                         && !noAnimations;
                 if (animationsAllowed) {
                     if (justAdded || justReplaced) {
@@ -576,9 +561,6 @@
                             animationProperties = ADD_ICON_PROPERTIES;
                             animate = true;
                         }
-                    } else if (justUndarkened) {
-                        animationProperties = UNDARK_PROPERTIES;
-                        animate = true;
                     } else if (visibleState != icon.getVisibleState()) {
                         animationProperties = DOT_ANIMATION_PROPERTIES;
                         animate = true;
@@ -591,17 +573,17 @@
                         animate = true;
                     }
                     if (needsCannedAnimation) {
-                        AnimationFilter animationFilter = mTempProperties.getAnimationFilter();
+                        AnimationFilter animationFilter = sTempProperties.getAnimationFilter();
                         animationFilter.reset();
                         animationFilter.combineFilter(
                                 ICON_ANIMATION_PROPERTIES.getAnimationFilter());
-                        mTempProperties.resetCustomInterpolators();
-                        mTempProperties.combineCustomInterpolators(ICON_ANIMATION_PROPERTIES);
+                        sTempProperties.resetCustomInterpolators();
+                        sTempProperties.combineCustomInterpolators(ICON_ANIMATION_PROPERTIES);
                         if (animationProperties != null) {
                             animationFilter.combineFilter(animationProperties.getAnimationFilter());
-                            mTempProperties.combineCustomInterpolators(animationProperties);
+                            sTempProperties.combineCustomInterpolators(animationProperties);
                         }
-                        animationProperties = mTempProperties;
+                        animationProperties = sTempProperties;
                         animationProperties.setDuration(CANNED_ANIMATION_DURATION);
                         animate = true;
                         mCannedAnimationStartIndex = indexOfChild(view);
@@ -610,11 +592,11 @@
                             && indexOfChild(view) > mCannedAnimationStartIndex
                             && (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
                             || visibleState != StatusBarIconView.STATE_HIDDEN)) {
-                        AnimationFilter animationFilter = mTempProperties.getAnimationFilter();
+                        AnimationFilter animationFilter = sTempProperties.getAnimationFilter();
                         animationFilter.reset();
                         animationFilter.animateX();
-                        mTempProperties.resetCustomInterpolators();
-                        animationProperties = mTempProperties;
+                        sTempProperties.resetCustomInterpolators();
+                        animationProperties = sTempProperties;
                         animationProperties.setDuration(CANNED_ANIMATION_DURATION);
                         animate = true;
                     }
@@ -638,7 +620,6 @@
             justAdded = false;
             justReplaced = false;
             needsCannedAnimation = false;
-            justUndarkened = false;
         }
 
         private boolean shouldVibrateChange(boolean inShelfChanged) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 078e818..c191618 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -509,7 +509,8 @@
             if (row.isRemoved()) {
                 continue;
             }
-            availableSpace -= child.getMinHeight() + notificationPadding;
+            availableSpace -= child.getMinHeight(true /* ignoreTemporaryStates */)
+                    + notificationPadding;
             if (availableSpace >= 0 && count < maximum) {
                 count++;
             } else if (availableSpace > -shelfSize) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 7aebfdc..200cada 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -300,6 +300,7 @@
     // Should match the values in PhoneWindowManager
     public static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
     public static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
+    static public final String SYSTEM_DIALOG_REASON_SCREENSHOT = "screenshot";
 
     private static final String BANNER_ACTION_CANCEL =
             "com.android.systemui.statusbar.banner_action_cancel";
@@ -338,7 +339,7 @@
 
     private static final int STATUS_OR_NAV_TRANSIENT =
             View.STATUS_BAR_TRANSIENT | View.NAVIGATION_BAR_TRANSIENT;
-    private static final long AUTOHIDE_TIMEOUT_MS = 3000;
+    private static final long AUTOHIDE_TIMEOUT_MS = 2250;
 
     /** The minimum delay in ms between reports of notification visibility. */
     private static final int VISIBILITY_REPORT_MIN_DELAY_MS = 500;
@@ -1124,7 +1125,7 @@
             }
         });
 
-        mLightBarController = new LightBarController(context);
+        mLightBarController = Dependency.get(LightBarController.class);
         if (mNavigationBar != null) {
             mNavigationBar.setLightBarController(mLightBarController);
         }
@@ -3320,7 +3321,6 @@
         } else {
             cancelAutohide();
         }
-        touchAutoDim();
     }
 
     protected int computeStatusBarMode(int oldVal, int newVal) {
@@ -3403,10 +3403,10 @@
         }
         // manually dismiss the volume panel when interacting with the nav bar
         if (changing && interacting && barWindow == StatusBarManager.WINDOW_NAVIGATION_BAR) {
+            touchAutoDim();
             dismissVolumeDialog();
         }
         checkBarModes();
-        touchAutoDim();
     }
 
     private void dismissVolumeDialog() {
@@ -4787,7 +4787,7 @@
             animateCollapsePanels();
             return true;
         }
-        if (mKeyguardUserSwitcher.hideIfNotSimple(true)) {
+        if (mKeyguardUserSwitcher != null && mKeyguardUserSwitcher.hideIfNotSimple(true)) {
             return true;
         }
         return false;
@@ -6808,6 +6808,7 @@
         row.setOnExpandClickListener(this);
         row.setRemoteViewClickHandler(mOnClickHandler);
         row.setInflationCallback(this);
+        row.setSecureStateProvider(this::isKeyguardCurrentlySecure);
 
         // Get the app name.
         // Note that Notification.Builder#bindHeaderAppName has similar logic
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
index 1411a54..f9c2130 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
@@ -159,6 +159,11 @@
         public void onScreenTurnedOff() {
             update(false /* updateAlways */);
         }
+
+        @Override
+        public void onKeyguardVisibilityChanged(boolean showing) {
+            update(false /* updateAlways */);
+        }
     };
 
     public boolean isTrustManaged() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 4e592db..75532d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -23,14 +23,12 @@
 import android.animation.TimeAnimator;
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.annotation.ColorInt;
 import android.annotation.FloatRange;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Canvas;
-import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.PointF;
 import android.graphics.PorterDuff;
@@ -1083,6 +1081,20 @@
 
     @Override
     public ExpandableView getChildAtPosition(float touchX, float touchY) {
+        return getChildAtPosition(touchX, touchY, true /* requireMinHeight */);
+
+    }
+
+    /**
+     * Get the child at a certain screen location.
+     *
+     * @param touchX the x coordinate
+     * @param touchY the y coordinate
+     * @param requireMinHeight Whether a minimum height is required for a child to be returned.
+     * @return the child at the given location.
+     */
+    private ExpandableView getChildAtPosition(float touchX, float touchY,
+            boolean requireMinHeight) {
         // find the view under the pointer, accounting for GONE views
         final int count = getChildCount();
         for (int childIdx = 0; childIdx < count; childIdx++) {
@@ -1101,7 +1113,7 @@
             int left = 0;
             int right = getWidth();
 
-            if (bottom - top >= mMinInteractionHeight
+            if ((bottom - top >= mMinInteractionHeight || !requireMinHeight)
                     && touchY >= top && touchY <= bottom && touchX >= left && touchX <= right) {
                 if (slidingChild instanceof ExpandableNotificationRow) {
                     ExpandableNotificationRow row = (ExpandableNotificationRow) slidingChild;
@@ -3220,7 +3232,7 @@
             case MotionEvent.ACTION_DOWN: {
                 final int y = (int) ev.getY();
                 mScrolledToTopOnFirstDown = isScrolledToTop();
-                if (getChildAtPosition(ev.getX(), y) == null) {
+                if (getChildAtPosition(ev.getX(), y, false /* requireMinHeight */) == null) {
                     setIsBeingDragged(false);
                     recycleVelocityTracker();
                     break;
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
index 3ebefbb..66d5ee1 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
@@ -29,6 +29,7 @@
 import android.os.IBinder;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.util.EventLog;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -95,6 +96,7 @@
             if (((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0)
                     || ((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED) != 0)) {
                 if (event.getAction() == MotionEvent.ACTION_UP) {
+                    EventLog.writeEvent(0x534e4554, "62187985"); // safety net logging
                     Toast.makeText(v.getContext(),
                             R.string.touch_filtered_warning,
                             Toast.LENGTH_SHORT).show();
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 694c72f..41a5dc8 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -75,6 +75,7 @@
 import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
+import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.plugins.VolumeDialog;
 import com.android.systemui.plugins.VolumeDialogController;
@@ -514,6 +515,9 @@
         if (mSafetyWarning != null) return 5000;
         if (mExpanded || mExpandButtonAnimationRunning) return 5000;
         if (mActiveStream == AudioManager.STREAM_MUSIC) return 1500;
+        if (mZenFooter.shouldShowIntroduction()) {
+            return 6000;
+        }
         return 3000;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
index 7464212..80e1629 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
@@ -152,6 +152,7 @@
                                 mController.getCurrentUser(), true /*shortVersion*/);
         Util.setText(mSummaryLine2, line2);
     }
+
     public boolean shouldShowIntroduction() {
         final boolean confirmed =  Prefs.getBoolean(mContext,
                 Prefs.Key.DND_CONFIRMED_ALARM_INTRODUCTION, false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index 66d00dd..65d9699 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -54,6 +54,7 @@
     @Before
     public void SysuiSetup() throws Exception {
         System.setProperty("dexmaker.share_classloader", "true");
+        mContext.setTheme(R.style.Theme_SystemUI);
         SystemUIFactory.createFromConfig(mContext);
 
         mRealInstrumentation = InstrumentationRegistry.getInstrumentation();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java
index 333e73d..b0c9f328 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java
@@ -30,6 +30,7 @@
     boolean dozing;
     float doubleTapX;
     float doubleTapY;
+    float aodDimmingScrimOpacity;
 
     @Override
     public void addCallback(@NonNull Callback callback) {
@@ -114,4 +115,9 @@
     @Override
     public void setDozeScreenBrightness(int value) {
     }
+
+    @Override
+    public void setAodDimmingScrim(float scrimOpacity) {
+        aodDimmingScrimOpacity = scrimOpacity;
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
index 4f59fc4..5e12781 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
@@ -30,6 +30,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 
 import android.os.PowerManager;
@@ -149,8 +150,6 @@
         mScreen.transitionTo(INITIALIZED, DOZE_AOD);
         mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING);
         mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED);
-
-        assertTrue(mScreen.isReady());
     }
 
     @Test
@@ -165,87 +164,77 @@
     }
 
     @Test
-    public void testNonPositiveBrightness_keepsPreviousBrightness() throws Exception {
+    public void testNonPositiveBrightness_keepsPreviousBrightnessAndScrim() throws Exception {
+        mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+        mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+
+        mSensor.sendSensorEvent(1);
+        mSensor.sendSensorEvent(0);
+
+        assertEquals(1, mServiceFake.screenBrightness);
+        assertEquals(10/255f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
+    }
+
+    @Test
+    public void pausingAod_softBlanks() throws Exception {
         mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
         mScreen.transitionTo(INITIALIZED, DOZE_AOD);
 
         mSensor.sendSensorEvent(2);
+
+        mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING);
+        mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED);
+
+        assertEquals(1f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
+
         mSensor.sendSensorEvent(0);
+        assertEquals(1f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
 
-        assertEquals(2, mServiceFake.screenBrightness);
+        mScreen.transitionTo(DOZE_AOD_PAUSED, DOZE_AOD);
+        assertEquals(1f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
     }
 
     @Test
-    public void readyWhenNotInitialized() {
-        assertTrue(mScreen.isReady());
-    }
-
-    @Test
-    public void readyWhenNotRegistered() {
+    public void pausingAod_softBlanks_withSpuriousSensorDuringPause() throws Exception {
         mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
-        mScreen.transitionTo(INITIALIZED, DOZE);
+        mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+        mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING);
+        mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED);
 
-        assertTrue(mScreen.isReady());
+        mSensor.sendSensorEvent(1);
+        assertEquals(1f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
     }
 
     @Test
-    public void notReadyWhenRegistered_butNoEventYet() {
+    public void pausingAod_unblanksAfterSensor() throws Exception {
         mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
         mScreen.transitionTo(INITIALIZED, DOZE_AOD);
 
-        assertFalse(mScreen.isReady());
-    }
+        mSensor.sendSensorEvent(2);
 
-    @Test
-    public void notReady_afterZeroBrightness() {
-        mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
-        mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+        mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING);
+        mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED);
 
         mSensor.sendSensorEvent(0);
 
-        assertFalse(mScreen.isReady());
+        mScreen.transitionTo(DOZE_AOD_PAUSED, DOZE_AOD);
+
+        mSensor.sendSensorEvent(2);
+
+        assertEquals(0f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
     }
 
     @Test
-    public void ready_afterNonZeroBrightness() {
+    public void pausingAod_unblanksIfSensorWasAlwaysReady() throws Exception {
         mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
         mScreen.transitionTo(INITIALIZED, DOZE_AOD);
 
-        mSensor.sendSensorEvent(1);
+        mSensor.sendSensorEvent(2);
 
-        assertTrue(mScreen.isReady());
-    }
+        mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING);
+        mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED);
+        mScreen.transitionTo(DOZE_AOD_PAUSED, DOZE_AOD);
 
-    @Test
-    public void notReady_nonZeroThenZeroBrightness() {
-        mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
-        mScreen.transitionTo(INITIALIZED, DOZE_AOD);
-
-        mSensor.sendSensorEvent(1);
-        mSensor.sendSensorEvent(0);
-
-        assertFalse(mScreen.isReady());
-    }
-
-    @Test
-    public void readyListener_getsCalled_whenRegistering() throws Exception {
-        Boolean[] ready = new Boolean[1];
-
-        mScreen.setBrightnessReadyListener((x) -> ready[0] = true);
-
-        assertTrue(ready[0]);
-    }
-
-    @Test
-    public void readyListener_getsCalled_whenReadyChanges() throws Exception {
-        Boolean[] ready = new Boolean[1];
-        mScreen.setBrightnessReadyListener((x) -> ready[0] = true);
-
-        mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
-        mScreen.transitionTo(INITIALIZED, DOZE_AOD);
-
-        ready[0] = null;
-        mSensor.sendSensorEvent(1);
-        assertTrue(ready[0]);
+        assertEquals(0f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 6a9dac4..a8ea1c0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -58,7 +58,6 @@
     private WakeLock mWakeLock;
     private Instrumentation mInstrumentation;
     private AlarmManager mAlarmManager;
-    private DozeScreenBrightness mDozeScreenBrightness;
 
     @BeforeClass
     public static void setupSuite() {
@@ -77,12 +76,10 @@
         mSensors = new FakeSensorManager(mContext);
         mHandler = new Handler(Looper.getMainLooper());
         mWakeLock = new WakeLockFake();
-        mDozeScreenBrightness = mock(DozeScreenBrightness.class);
 
         mInstrumentation.runOnMainSync(() -> {
             mTriggers = new DozeTriggers(mContext, mMachine, mHost, mAlarmManager,
-                    mConfig, mParameters, mSensors, mHandler, mDozeScreenBrightness,
-                    mWakeLock, true);
+                    mConfig, mParameters, mSensors, mHandler, mWakeLock, true);
         });
     }
 
@@ -115,22 +112,4 @@
         verify(mMachine).requestPulse(anyInt());
     }
 
-    @Test
-    public void unpausing_fromPaused_waitsForBrightnessReady() throws Exception {
-        when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE_AOD_PAUSED);
-
-        mTriggers.recalculatePausing(true /* proxFar */, false /* brightnessReady */);
-        verify(mMachine, never()).requestState(any());
-
-        mTriggers.recalculatePausing(true /* proxFar */, true /* brightnessReady */);
-        verify(mMachine).requestState(DozeMachine.State.DOZE_AOD);
-    }
-
-    @Test
-    public void unpausing_fromPausing_doesntWaitForBrightnessReady() throws Exception {
-        when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE_AOD_PAUSED);
-
-        mTriggers.recalculatePausing(true /* proxFar */, false /* brightnessReady */);
-        verify(mMachine).requestState(DozeMachine.State.DOZE_AOD);
-    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/SlashImageViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/SlashImageViewTest.java
index 9fe3e10..98ca1b4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/SlashImageViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/SlashImageViewTest.java
@@ -76,6 +76,19 @@
         assertTrue(mSlashView.getSlashDrawable() == null);
     }
 
+    @Test
+    public void testSetImageDrawableUsesDrawableLevel() {
+        SlashImageView iv = new SlashImageView(mContext);
+        Drawable mockDrawable = mock(Drawable.class);
+        mockDrawable.setLevel(2);
+        assertTrue(mockDrawable.getLevel() == 2);
+
+        iv.setImageDrawable(mockDrawable);
+
+        // Make sure setting the drawable didn't reset its level to 0
+        assertTrue(mockDrawable.getLevel() == 2);
+    }
+
     // Expose getSlashDrawable
     private static class TestableSlashImageView extends SlashImageView {
         TestableSlashImageView(Context c) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
index 0500a54..004ff29 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
@@ -21,13 +21,19 @@
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_QS_VALUE;
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_ACTION;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import static java.lang.Thread.sleep;
+
 import android.content.Intent;
 import android.metrics.LogMaker;
 import android.support.test.filters.SmallTest;
@@ -66,10 +72,10 @@
         mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
         mHost = mock(QSTileHost.class);
         when(mHost.indexOf(spec)).thenReturn(POSITION);
-        mTestableLooper.runWithLooper(() -> {
-            mTile = new TileImpl(mHost);
-            mTile.setTileSpec(spec);
-        });
+
+        mTile = spy(new TileImpl(mHost));
+        mTile.mHandler = mTile.new H(mTestableLooper.getLooper());
+        mTile.setTileSpec(spec);
     }
 
     @Test
@@ -94,12 +100,38 @@
     public void testPopulate() {
         LogMaker maker = mock(LogMaker.class);
         when(maker.setSubtype(anyInt())).thenReturn(maker);
+        when(maker.addTaggedData(anyInt(), any())).thenReturn(maker);
         mTile.getState().value = true;
         mTile.populate(maker);
         verify(maker).addTaggedData(eq(FIELD_QS_VALUE), eq(1));
         verify(maker).addTaggedData(eq(FIELD_QS_POSITION), eq(POSITION));
     }
 
+    @Test
+    public void testStaleTimeout() throws InterruptedException {
+        when(mTile.getStaleTimeout()).thenReturn(5l);
+        clearInvocations(mTile);
+
+        mTile.handleRefreshState(null);
+        mTestableLooper.processAllMessages();
+        verify(mTile, never()).handleStale();
+
+        sleep(10);
+        mTestableLooper.processAllMessages();
+        verify(mTile).handleStale();
+    }
+
+    @Test
+    public void testStaleListening() {
+        mTile.handleStale();
+        mTestableLooper.processAllMessages();
+        verify(mTile).handleSetListening(eq(true));
+
+        mTile.handleRefreshState(null);
+        mTestableLooper.processAllMessages();
+        verify(mTile).handleSetListening(eq(false));
+    }
+
     private class TileLogMatcher implements ArgumentMatcher<LogMaker> {
 
         private final int mCategory;
@@ -164,7 +196,7 @@
         }
 
         @Override
-        protected void setListening(boolean listening) {
+        protected void handleSetListening(boolean listening) {
 
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
index 2f6511c..58ff46a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
@@ -134,4 +134,16 @@
         row.setAboveShelf(false);
         verify(listener).onAboveShelfStateChanged(false);
     }
+
+    @Test
+    public void testClickSound() throws Exception {
+        Assert.assertTrue("Should play sounds by default.", mGroup.isSoundEffectsEnabled());
+        mGroup.setDark(true /* dark */, false /* fade */, 0 /* delay */);
+        mGroup.setSecureStateProvider(()-> false);
+        Assert.assertFalse("Shouldn't play sounds when dark and trusted.",
+                mGroup.isSoundEffectsEnabled());
+        mGroup.setSecureStateProvider(()-> true);
+        Assert.assertTrue("Should always play sounds when not trusted.",
+                mGroup.isSoundEffectsEnabled());
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java
index 18c5756..972eddb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationDataTest.java
@@ -135,5 +135,11 @@
         public NotificationChannel getChannel(String key) {
             return new NotificationChannel(null, null, 0);
         }
+
+        @Override
+        protected boolean getRanking(String key, NotificationListenerService.Ranking outRanking) {
+            super.getRanking(key, outRanking);
+            return true;
+        }
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index b6827ea..88fa659 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -121,7 +121,7 @@
         mDefaultNotificationChannel = new NotificationChannel(
                 NotificationChannel.DEFAULT_CHANNEL_ID, TEST_CHANNEL_NAME,
                 NotificationManager.IMPORTANCE_LOW);
-        mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, 0, 0,
+        mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
                 new Notification(), UserHandle.CURRENT, null, 0);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
index 12a4399..f8fd53d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
@@ -185,7 +185,9 @@
         countDownLatch.await();
     }
 
+    /* Cancelling requires us to be on the UI thread otherwise we might have a race */
     @Test
+    @UiThreadTest
     public void testSupersedesExistingTask() throws Exception {
         mNotificationInflater.inflateNotificationViews();
         mNotificationInflater.setIsLowPriority(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
new file mode 100644
index 0000000..4051220
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 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.phone;
+
+import static org.mockito.Mockito.mock;
+
+import android.content.Context;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.UiThreadTest;
+import android.view.ContextThemeWrapper;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.keyguard.DismissCallbackRegistry;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class KeyguardBouncerTest extends SysuiTestCase {
+
+    @UiThreadTest
+    @Test
+    public void inflateDetached() {
+        final ViewGroup container = new FrameLayout(getContext());
+        final KeyguardBouncer bouncer = new KeyguardBouncer(getContext(),
+                mock(ViewMediatorCallback.class), mock(LockPatternUtils.class), container, mock(
+                DismissCallbackRegistry.class));
+
+        // Detached bouncer should still be able to be inflated
+        bouncer.inflateView();
+    }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java
index ed1491d3..500d620 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NearestTouchFrameTest.java
@@ -71,6 +71,24 @@
     }
 
     @Test
+    public void testInvisibleViews() {
+        View left = mockViewAt(0, 0, 10, 10);
+        View right = mockViewAt(20, 0, 10, 10);
+        when(left.getVisibility()).thenReturn(View.INVISIBLE);
+
+        mNearestTouchFrame.addView(left);
+        mNearestTouchFrame.addView(right);
+        mNearestTouchFrame.onMeasure(0, 0);
+
+        MotionEvent ev = MotionEvent.obtain(0, 0, 0,
+                12 /* x */, 5 /* y */, 0);
+        mNearestTouchFrame.onTouchEvent(ev);
+        verify(left, never()).onTouchEvent(eq(ev));
+        verify(right, never()).onTouchEvent(eq(ev));
+        ev.recycle();
+    }
+
+    @Test
     public void testHorizontalSelection_Left() {
         View left = mockViewAt(0, 0, 10, 10);
         View right = mockViewAt(20, 0, 10, 10);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java
index a915cb2..b22a646 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ExtensionControllerImplTest.java
@@ -27,7 +27,6 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
-import android.util.Log;
 
 import com.android.systemui.Dependency;
 import com.android.systemui.SysuiTestCase;
@@ -145,7 +144,6 @@
     @Test
     @RunWithLooper
     public void testSortOrder() {
-        Log.d("TestTest", "Config " + mContext.getResources().getConfiguration().uiMode);
         Object def = new Object();
         Object uiMode = new Object();
         Object tuner = new Object();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/IconLoggerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/IconLoggerImplTest.java
index 66a8561..ec994a1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/IconLoggerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/IconLoggerImplTest.java
@@ -32,6 +32,7 @@
 import static java.lang.Thread.sleep;
 
 import android.metrics.LogMaker;
+import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.MessageHandler;
@@ -48,6 +49,7 @@
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
+@SmallTest
 public class IconLoggerImplTest extends SysuiTestCase {
 
     private MetricsLogger mMetricsLogger;
@@ -172,4 +174,4 @@
             return true;
         }));
     }
-}
\ No newline at end of file
+}
diff --git a/packages/VpnDialogs/res/values-hi/strings.xml b/packages/VpnDialogs/res/values-hi/strings.xml
index 15f69c6..a599b25 100644
--- a/packages/VpnDialogs/res/values-hi/strings.xml
+++ b/packages/VpnDialogs/res/values-hi/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="prompt" msgid="3183836924226407828">"कनेक्शन अनुरोध"</string>
-    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> VPN कनेक्‍शन सेट करना चाहता है जो उसे नेटवर्क ट्रैफ़िक मॉनीटर करने देता है. केवल तभी स्‍वीकार करें, जबकि आप स्रोत पर विश्वास करते हों. VPN सक्रिय होने पर आपकी स्‍क्रीन पर ऊपर &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; दिखाई देता है."</string>
+    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> VPN कनेक्‍शन सेट करना चाहता है जो उसे नेटवर्क ट्रैफ़िक मॉनीटर करने देता है. केवल तभी स्‍वीकार करें, जबकि आप स्रोत पर भरोसा करते हों. VPN सक्रिय होने पर आपकी स्‍क्रीन पर ऊपर &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; दिखाई देता है."</string>
     <string name="legacy_title" msgid="192936250066580964">"VPN कनेक्‍ट है"</string>
     <string name="configure" msgid="4905518375574791375">"कॉन्फ़िगर करें"</string>
     <string name="disconnect" msgid="971412338304200056">"डिस्‍कनेक्‍ट करें"</string>
diff --git a/packages/VpnDialogs/res/values-vi/strings.xml b/packages/VpnDialogs/res/values-vi/strings.xml
index c7df53f..6663636 100644
--- a/packages/VpnDialogs/res/values-vi/strings.xml
+++ b/packages/VpnDialogs/res/values-vi/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="prompt" msgid="3183836924226407828">"Yêu cầu kết nối"</string>
-    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> muốn thiết lập kết nối VPN cho phép ứng dụng giám sát lưu lượng truy cập mạng. Chỉ chấp nhận nếu bạn tin tưởng nguồn. &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; xuất hiện ở đầu màn hình của bạn khi VPN đang hoạt động."</string>
+    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> muốn thiết lập kết nối VPN cho phép ứng dụng giám sát lưu lượng truy cập mạng. Chỉ chấp nhận nếu bạn tin tưởng nguồn. Biểu tượng &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; xuất hiện ở đầu màn hình của bạn khi VPN đang hoạt động."</string>
     <string name="legacy_title" msgid="192936250066580964">"VPN được kết nối"</string>
     <string name="configure" msgid="4905518375574791375">"Định cấu hình"</string>
     <string name="disconnect" msgid="971412338304200056">"Ngắt kết nối"</string>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/color/qs_detail_progress_track.xml b/packages/overlays/SysuiDarkThemeOverlay/res/color/qs_detail_progress_track.xml
new file mode 100644
index 0000000..c56382e
--- /dev/null
+++ b/packages/overlays/SysuiDarkThemeOverlay/res/color/qs_detail_progress_track.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- I really don't want to define this, but the View that uses this asset uses both the
+         light and dark accent colors. -->
+    <item android:alpha="0.6" android:drawable="@*android:color/accent_device_default_light" />
+</selector>
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 9fbec70..f15749f 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -33,7 +33,7 @@
     // The view became hidden.
     TYPE_CLOSE = 2;
 
-    // The view switched to detail mode (most relevant for quick settings tiles)
+    // The view switched to detail mode (most relevant for quick settings tiles and notifications)
     TYPE_DETAIL = 3;
 
     // The view or control was activated.
@@ -70,6 +70,9 @@
     // Type for APP_TRANSITION_REPORTED_DRAWN event: The activity was started with restoring from
     // a bundle.
     TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE = 13;
+
+    // The view switched to summary mode (most relevant for notifications)
+    TYPE_COLLAPSE = 14;
   }
 
   // Types of alerts, as bit field values
@@ -158,6 +161,16 @@
     CAMERA_EXTERNAL_USED = 2;
   }
 
+  // TextClassifier entity types.
+  enum TextClassifierEntityType {
+    TEXT_CLASSIFIER_TYPE_UNKNOWN = 1;
+    TEXT_CLASSIFIER_TYPE_OTHER = 2;
+    TEXT_CLASSIFIER_TYPE_EMAIL = 3;
+    TEXT_CLASSIFIER_TYPE_PHONE = 4;
+    TEXT_CLASSIFIER_TYPE_ADDRESS = 5;
+    TEXT_CLASSIFIER_TYPE_URL = 6;
+  }
+
   // Known visual elements: views or controls.
   enum View {
     // Unknown view
@@ -4300,6 +4313,222 @@
     // OS: O MR
     FIELD_NUM_STATUS_ICONS = 1095;
 
+    // ACTION: Logged when user tries to pair a Bluetooth device without name from Settings app
+    // CATEGORY: SETTINGS
+    // OS: O MR
+    ACTION_SETTINGS_BLUETOOTH_PAIR_DEVICES_WITHOUT_NAMES = 1096;
+
+    // FIELD - Whether smart suggestion ranking was enabled or not
+    // Type: int encoded boolean
+    // CATEGORY: SETTINGS
+    // OS: O MR
+    FIELD_SETTINGS_SMART_SUGGESTIONS_ENABLED = 1097;
+
+    // ACTION: The device boots
+    ACTION_BOOT = 1098;
+
+    // FIELD: A string value representing some state of the platform, e.g., boot reason
+    FIELD_PLATFORM_REASON = 1099;
+
+    // CATEGORY: The category for all actions relating to selection session logging.
+    // OS: O MR
+    TEXT_SELECTION_SESSION = 1100;
+
+    // ACTION: A selection session started (i.e. the selection handles appeared)
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    ACTION_TEXT_SELECTION_START = 1101;
+
+    // ACTION: The user modified the selection (e.g. by dragging the handles)
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    ACTION_TEXT_SELECTION_MODIFY = 1102;
+
+    // ACTION: The user modified the selection by pressing the "select all" button.
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    ACTION_TEXT_SELECTION_SELECT_ALL = 1103;
+
+    // ACTION: The user modified the selection by pressing on a word in a multi word selection
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    ACTION_TEXT_SELECTION_RESET = 1104;
+
+    // ACTION: Smart selection made a single word prediction
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    ACTION_TEXT_SELECTION_SMART_SINGLE = 1105;
+
+    // ACTION: Smart selection made a multi word prediction
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    ACTION_TEXT_SELECTION_SMART_MULTI = 1106;
+
+    // ACTION: The app made an automatic selection on the user's behalf (not smart selection)
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    ACTION_TEXT_SELECTION_AUTO = 1107;
+
+    // ACTION: A selection session ended with the user typing over the text
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    ACTION_TEXT_SELECTION_OVERTYPE = 1108;
+
+    // ACTION: A selection session ended with the user copying the text
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    ACTION_TEXT_SELECTION_COPY = 1109;
+
+    // ACTION: A selection session ended with the user pasting over the text
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    ACTION_TEXT_SELECTION_PASTE = 1110;
+
+    // ACTION: A selection session ended with the user cutting the text
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    ACTION_TEXT_SELECTION_CUT = 1111;
+
+    // ACTION: A selection session ended with the user pressing the share button
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    ACTION_TEXT_SELECTION_SHARE = 1112;
+
+    // ACTION: A selection session ended with the user pressing the smart share button
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    ACTION_TEXT_SELECTION_SMART_SHARE = 1113;
+
+    // ACTION: A selection session ended with the user dragging the text
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    ACTION_TEXT_SELECTION_DRAG = 1114;
+
+    // ACTION: A selection session ended with the user abandoning the selection
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    ACTION_TEXT_SELECTION_ABANDON = 1115;
+
+    // ACTION: A selection session ended with the user picking an unhandled action bar item
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    ACTION_TEXT_SELECTION_OTHER = 1116;
+
+    // FIELD: Time in milliseconds from the start of the session to this event
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    FIELD_SELECTION_SINCE_START = 1117;
+
+    // FIELD: time in milliseconds between the last event in the session and this one
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    FIELD_SELECTION_SINCE_PREVIOUS = 1118;
+
+    // FIELD: a random uid for a selection session (lasting from select start to end)
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    FIELD_SELECTION_SESSION_ID = 1119;
+
+    // FIELD: the sequence number of the event in the session
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    FIELD_SELECTION_SESSION_INDEX = 1120;
+
+    // FIELD: a concatenation of the widget type and ML model version.
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    FIELD_SELECTION_VERSION_TAG = 1121;
+
+    // FIELD: text select start offset in words (as defined by the ICU BreakIterator), stored as two
+    //        packed 16bit integers. (start in MSBs, end in LSBs)
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    FIELD_SELECTION_RANGE = 1122;
+
+    // FIELD: smart text selection start offset in words (as defined by the ICU BreakIterator),
+    //        stored as two packed 16bit integers. (start in MSBs, end in LSBs)
+    // CATEGORY: TEXT_SELECTION_SESSION
+    // OS: O MR
+    FIELD_SELECTION_SMART_RANGE = 1123;
+
+    // The value of an autofillable and savable view was reset
+    // Package: Package of app that was autofilled
+    // OS: O MR
+    // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+    // Tag FIELD_AUTOFILL_PREVIOUS_LENGTH: the previous length of the value
+    AUTOFILL_VALUE_RESET = 1124;
+
+    // Tag of AUTOFILL_VALUE_RESET
+    // OS: O MR
+    FIELD_AUTOFILL_PREVIOUS_LENGTH = 1125;
+
+    // An autofill dataset authentification succeeded
+    // Package: Package of app that was autofilled
+    // OS: O MR
+    // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+    AUTOFILL_DATASET_AUTHENTICATED = 1126;
+
+    // An autofill service provided an invalid dataset authentification
+    // Package: Package of app that was autofilled
+    // OS: O MR
+    // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+    AUTOFILL_INVALID_DATASET_AUTHENTICATION = 1127;
+
+    // An autofill service provided an invalid authentification extra
+    // Package: Package of app that was autofilled
+    // OS: O MR
+    // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+    AUTOFILL_INVALID_AUTHENTICATION = 1128;
+
+    // An autofill service used a custom description (using RemoteViews) in the Save affordance
+    // Package: Package of app that is autofilled
+    // OS: O MR
+    // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+    // Tag FIELD_AUTOFILL_SAVE_TYPE: Type of save object passed by the service
+    AUTOFILL_SAVE_CUSTOM_DESCRIPTION = 1129;
+
+    // FIELD - Type of save object passed by the service when the Save UI is shown
+    // OS: O MR
+    FIELD_AUTOFILL_SAVE_TYPE = 1130;
+
+    // An autofill service used a custom subtitle (String) in the Save affordance
+    // Package: Package of app that is autofilled
+    // OS: O MR
+    // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+    // Tag FIELD_AUTOFILL_SAVE_TYPE: Type of save object passed by the service
+    AUTOFILL_SAVE_CUSTOM_SUBTITLE = 1131;
+
+    // User tapped a link in the custom description of the Save affordance provided by an autofill service
+    // Package: Package of app that is autofilled
+    // OS: O MR
+    // Type TYPE_UNKNOWN: The link was not properly set by the service
+    // Type TYPE_OPEN: The link launched an activity
+    // Type TYPE_FAILURE: The link could not launc an activity
+    // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+    // Tag FIELD_AUTOFILL_SAVE_TYPE: Type of save object passed by the service
+    AUTOFILL_SAVE_LINK_TAPPED = 1132;
+
+    // Result of the validation on save when an autofill service provided a validator
+    // Package: Package of app that is autofilled
+    // OS: O MR
+    // Type TYPE_FAILURE: The validation could not be performed due to an error
+    // Type TYPE_SUCCESS: The validation passed
+    // Type TYPE_DISMISS: The validation failed
+    // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request
+    // Tag FIELD_AUTOFILL_SAVE_TYPE: Type of save object passed by the service
+    AUTOFILL_SAVE_VALIDATION = 1133;
+
+    // Result of an operation in the autofill save affordance after the user tapped a link in the custom description
+    // provided by the autofill service
+    // Package: Package of app that is autofilled
+    // OS: O MR
+    // Type TYPE_OPEN: The save affordance was restored
+    // Type TYPE_DISMISS: The save affordcance was destroyed
+    // Type TYPE_FAILURE: An invalid opperation was reported by the app's AutofillManager
+    AUTOFILL_PENDING_SAVE_UI_OPERATION = 1134;
+
+    // ---- End O-MR1 Constants, all O-MR1 constants go above this line ----
+
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
   }
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index ddc819d..a1c75bf 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -650,7 +650,7 @@
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service == null) return false;
-                return Objects.equals(packageName, service.getPackageName());
+                return Objects.equals(packageName, service.getServicePackageName());
             }
         }
 
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 20ccee2..e28e1c9 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -34,6 +34,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
 import android.os.Binder;
 import android.os.Bundle;
@@ -145,8 +146,9 @@
         updateLocked(disabled);
     }
 
+    @Nullable
     CharSequence getServiceName() {
-        final String packageName = getPackageName();
+        final String packageName = getServicePackageName();
         if (packageName == null) {
             return null;
         }
@@ -161,7 +163,8 @@
         }
     }
 
-    String getPackageName() {
+    @Nullable
+    String getServicePackageName() {
         final ComponentName serviceComponent = getServiceComponentName();
         if (serviceComponent != null) {
             return serviceComponent.getPackageName();
@@ -481,10 +484,16 @@
         sendStateToClients(true);
     }
 
+    @NonNull
     CharSequence getServiceLabel() {
         return mInfo.getServiceInfo().loadLabel(mContext.getPackageManager());
     }
 
+    @NonNull
+    Drawable getServiceIcon() {
+        return mInfo.getServiceInfo().loadIcon(mContext.getPackageManager());
+    }
+
     /**
      * Initializes the last fill selection after an autofill service returned a new
      * {@link FillResponse}.
@@ -533,9 +542,9 @@
     /**
      * Updates the last fill selection when an dataset authentication was selected.
      */
-    void setDatasetAuthenticationSelected(@Nullable String selectedDataset, int sessionId) {
+    void logDatasetAuthenticationSelected(@Nullable String selectedDataset, int sessionId) {
         synchronized (mLock) {
-            if (isValidEventLocked("setDatasetAuthenticationSelected()", sessionId)) {
+            if (isValidEventLocked("logDatasetAuthenticationSelected()", sessionId)) {
                 mEventHistory.addEvent(
                         new Event(Event.TYPE_DATASET_AUTHENTICATION_SELECTED, selectedDataset));
             }
@@ -545,9 +554,9 @@
     /**
      * Updates the last fill selection when an save Ui is shown.
      */
-    void setSaveShown(int sessionId) {
+    void logSaveShown(int sessionId) {
         synchronized (mLock) {
-            if (isValidEventLocked("setSaveShown()", sessionId)) {
+            if (isValidEventLocked("logSaveShown()", sessionId)) {
                 mEventHistory.addEvent(new Event(Event.TYPE_SAVE_SHOWN, null));
             }
         }
@@ -556,7 +565,7 @@
     /**
      * Updates the last fill response when a dataset was selected.
      */
-    void setDatasetSelected(@Nullable String selectedDataset, int sessionId) {
+    void logDatasetSelected(@Nullable String selectedDataset, int sessionId) {
         synchronized (mLock) {
             if (isValidEventLocked("setDatasetSelected()", sessionId)) {
                 mEventHistory.addEvent(new Event(Event.TYPE_DATASET_SELECTED, selectedDataset));
@@ -624,7 +633,7 @@
 
     void destroySessionsLocked() {
         if (mSessions.size() == 0) {
-            mUi.destroyAll(AutofillManager.NO_SESSION, null, null);
+            mUi.destroyAll(null, null, false);
             return;
         }
         while (mSessions.size() > 0) {
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index 086dd29..236fbfd 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.metrics.LogMaker;
 import android.os.Bundle;
 import android.service.autofill.Dataset;
 import android.util.ArrayMap;
@@ -25,6 +26,8 @@
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Objects;
@@ -99,4 +102,14 @@
         }
         return fields;
     }
+
+    @NonNull
+    public static LogMaker newLogMaker(int category, String packageName,
+            String servicePackageName) {
+        final LogMaker log = new LogMaker(category).setPackageName(packageName);
+        if (servicePackageName != null) {
+            log.addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, servicePackageName);
+        }
+        return log;
+    }
 }
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index dd98053..af55807 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -387,8 +387,10 @@
                 @Override
                 public void executeMessage(Message message) {
                     if (mDestroyed) {
-                        Slog.w(LOG_TAG, "Not handling " + message + " as service for "
-                                + mComponentName + " is already destroyed");
+                        if (sVerbose) {
+                            Slog.v(LOG_TAG, "Not handling " + message + " as service for "
+                                    + mComponentName + " is already destroyed");
+                        }
                         return;
                     }
                     switch (message.what) {
@@ -574,6 +576,12 @@
 
         @Override
         public void run() {
+            synchronized (mLock) {
+                if (isCancelledLocked()) {
+                    if (sDebug) Slog.d(LOG_TAG, "run() called after canceled: " + mRequest);
+                    return;
+                }
+            }
             final RemoteFillService remoteService = getService();
             if (remoteService != null) {
                 try {
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 95db603..ff6e94b 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -268,7 +268,7 @@
             value = state.getCurrentValue();
             if (value == null) {
                 if (sDebug) Slog.d(TAG, "getValue(): no current value for " + id);
-                value = getValueFromContexts(id);
+                value = getValueFromContextsLocked(id);
             }
         }
         if (value != null) {
@@ -276,7 +276,7 @@
                 return value.getTextValue().toString();
             }
             if (value.isList()) {
-                final CharSequence[] options = getAutofillOptionsFromContexts(id);
+                final CharSequence[] options = getAutofillOptionsFromContextsLocked(id);
                 if (options != null) {
                     final int index = value.getListValue();
                     final CharSequence option = options[index];
@@ -339,21 +339,21 @@
      * Cancels the last request sent to the {@link #mRemoteFillService}.
      */
     private void cancelCurrentRequestLocked() {
-        int canceledRequest = mRemoteFillService.cancelCurrentRequest();
+        final int canceledRequest = mRemoteFillService.cancelCurrentRequest();
 
         // Remove the FillContext as there will never be a response for the service
         if (canceledRequest != INVALID_REQUEST_ID && mContexts != null) {
-            int numContexts = mContexts.size();
+            final int numContexts = mContexts.size();
 
             // It is most likely the last context, hence search backwards
             for (int i = numContexts - 1; i >= 0; i--) {
                 if (mContexts.get(i).getRequestId() == canceledRequest) {
+                    if (sDebug) Slog.d(TAG, "cancelCurrentRequest(): id = " + canceledRequest);
                     mContexts.remove(i);
                     break;
                 }
             }
         }
-
     }
 
     /**
@@ -411,7 +411,7 @@
         mPackageName = packageName;
         mClient = IAutoFillManagerClient.Stub.asInterface(client);
 
-        mMetricsLogger.action(MetricsEvent.AUTOFILL_SESSION_STARTED, mPackageName);
+        writeLog(MetricsEvent.AUTOFILL_SESSION_STARTED);
     }
 
     /**
@@ -456,14 +456,7 @@
             }
         }
         if (response == null) {
-            if (sVerbose) Slog.v(TAG, "canceling session " + id + " when server returned null");
-            if ((requestFlags & FLAG_MANUAL_REQUEST) != 0) {
-                getUiForShowing().showError(R.string.autofill_error_cannot_autofill, this);
-            }
-            mService.resetLastResponse();
-            // Nothing to be done, but need to notify client.
-            notifyUnavailableToClient();
-            removeSelf();
+            processNullResponseLocked(requestFlags);
             return;
         }
 
@@ -472,19 +465,16 @@
         if ((response.getDatasets() == null || response.getDatasets().isEmpty())
                         && response.getAuthentication() == null) {
             // Response is "empty" from an UI point of view, need to notify client.
-            notifyUnavailableToClient();
+            notifyUnavailableToClient(false);
         }
         synchronized (mLock) {
             processResponseLocked(response, requestFlags);
         }
 
-        final LogMaker log = (new LogMaker(MetricsEvent.AUTOFILL_REQUEST))
+        final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_REQUEST, servicePackageName)
                 .setType(MetricsEvent.TYPE_SUCCESS)
-                .setPackageName(mPackageName)
                 .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS,
-                        response.getDatasets() == null ? 0 : response.getDatasets().size())
-                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE,
-                        servicePackageName);
+                        response.getDatasets() == null ? 0 : response.getDatasets().size());
         mMetricsLogger.write(log);
     }
 
@@ -500,10 +490,8 @@
             }
             mService.resetLastResponse();
         }
-        LogMaker log = (new LogMaker(MetricsEvent.AUTOFILL_REQUEST))
-                .setType(MetricsEvent.TYPE_FAILURE)
-                .setPackageName(mPackageName)
-                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, servicePackageName);
+        LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_REQUEST, servicePackageName)
+                .setType(MetricsEvent.TYPE_FAILURE);
         mMetricsLogger.write(log);
 
         getUiForShowing().showError(message, this);
@@ -522,11 +510,8 @@
                 return;
             }
         }
-        LogMaker log = (new LogMaker(
-                MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST))
-                .setType(MetricsEvent.TYPE_SUCCESS)
-                .setPackageName(mPackageName)
-                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, servicePackageName);
+        LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST, servicePackageName)
+                .setType(MetricsEvent.TYPE_SUCCESS);
         mMetricsLogger.write(log);
 
         // Nothing left to do...
@@ -546,11 +531,8 @@
                 return;
             }
         }
-        LogMaker log = (new LogMaker(
-                MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST))
-                .setType(MetricsEvent.TYPE_FAILURE)
-                .setPackageName(mPackageName)
-                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, servicePackageName);
+        LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_DATA_SAVE_REQUEST, servicePackageName)
+                .setType(MetricsEvent.TYPE_FAILURE);
         mMetricsLogger.write(log);
 
         getUiForShowing().showError(message, this);
@@ -584,19 +566,23 @@
     // FillServiceCallbacks
     @Override
     public void authenticate(int requestId, int datasetIndex, IntentSender intent, Bundle extras) {
+        if (sDebug) {
+            Slog.d(TAG, "authenticate(): requestId=" + requestId + "; datasetIdx=" + datasetIndex
+                    + "; intentSender=" + intent);
+        }
         final Intent fillInIntent;
         synchronized (mLock) {
-            synchronized (mLock) {
-                if (mDestroyed) {
-                    Slog.w(TAG, "Call to Session#authenticate() rejected - session: "
-                            + id + " destroyed");
-                    return;
-                }
+            if (mDestroyed) {
+                Slog.w(TAG, "Call to Session#authenticate() rejected - session: "
+                        + id + " destroyed");
+                return;
             }
-            fillInIntent = createAuthFillInIntent(
-                    getFillContextByRequestIdLocked(requestId).getStructure(), extras);
+            fillInIntent = createAuthFillInIntentLocked(requestId, extras);
+            if (fillInIntent == null) {
+                forceRemoveSelfLocked();
+                return;
+            }
         }
-
         mService.setAuthenticationSelected(id);
 
         final int authenticationId = AutofillManager.makeAuthenticationId(requestId, datasetIndex);
@@ -620,7 +606,7 @@
                 return;
             }
         }
-        mHandlerCaller.getHandler().post(() -> autoFill(requestId, datasetIndex, dataset));
+        mHandlerCaller.getHandler().post(() -> autoFill(requestId, datasetIndex, dataset, true));
     }
 
     // AutoFillUiCallback
@@ -748,16 +734,25 @@
         }
 
         final Parcelable result = data.getParcelable(AutofillManager.EXTRA_AUTHENTICATION_RESULT);
+        if (sDebug) Slog.d(TAG, "setAuthenticationResultLocked(): result=" + result);
         if (result instanceof FillResponse) {
-            final FillResponse response = (FillResponse) result;
-            mMetricsLogger.action(MetricsEvent.AUTOFILL_AUTHENTICATED, mPackageName);
-            replaceResponseLocked(authenticatedResponse, response);
+            writeLog(MetricsEvent.AUTOFILL_AUTHENTICATED);
+            replaceResponseLocked(authenticatedResponse, (FillResponse) result);
         } else if (result instanceof Dataset) {
             if (datasetIdx != AutofillManager.AUTHENTICATION_ID_DATASET_ID_UNDEFINED) {
+                writeLog(MetricsEvent.AUTOFILL_DATASET_AUTHENTICATED);
                 final Dataset dataset = (Dataset) result;
                 authenticatedResponse.getDatasets().set(datasetIdx, dataset);
-                autoFill(requestId, datasetIdx, dataset);
+                autoFill(requestId, datasetIdx, dataset, false);
+            } else {
+                writeLog(MetricsEvent.AUTOFILL_INVALID_DATASET_AUTHENTICATION);
             }
+        } else {
+            if (result != null) {
+                Slog.w(TAG, "service returned invalid auth type: " + result);
+            }
+            writeLog(MetricsEvent.AUTOFILL_INVALID_AUTHENTICATION);
+            processNullResponseLocked(0);
         }
     }
 
@@ -770,6 +765,44 @@
         mHasCallback = hasIt;
     }
 
+    @Nullable
+    private FillResponse getLastResponseLocked(@Nullable String logPrefix) {
+        if (mContexts == null) {
+            if (sDebug && logPrefix != null) Slog.d(TAG, logPrefix + ": no contexts");
+            return null;
+        }
+        if (mResponses == null) {
+            // Happens when the activity / session was finished before the service replied, or
+            // when the service cannot autofill it (and returned a null response).
+            if (sVerbose && logPrefix != null) {
+                Slog.v(TAG, logPrefix + ": no responses on session");
+            }
+            return null;
+        }
+
+        final int lastResponseIdx = getLastResponseIndexLocked();
+        if (lastResponseIdx < 0) {
+            if (logPrefix != null) {
+                Slog.w(TAG, logPrefix + ": did not get last response. mResponses=" + mResponses
+                        + ", mViewStates=" + mViewStates);
+            }
+            return null;
+        }
+
+        final FillResponse response = mResponses.valueAt(lastResponseIdx);
+        if (sVerbose && logPrefix != null) {
+            Slog.v(TAG, logPrefix + ": mResponses=" + mResponses + ", mContexts=" + mContexts
+                    + ", mViewStates=" + mViewStates);
+        }
+        return response;
+    }
+
+    @Nullable
+    private SaveInfo getSaveInfoLocked() {
+        final FillResponse response = getLastResponseLocked(null);
+        return response == null ? null : response.getSaveInfo();
+    }
+
     /**
      * Shows the save UI, when session can be saved.
      *
@@ -781,32 +814,8 @@
                     + id + " destroyed");
             return false;
         }
-        if (mContexts == null) {
-            Slog.d(TAG, "showSaveLocked(): no contexts");
-            return true;
-        }
-        if (mResponses == null) {
-            // Happens when the activity / session was finished before the service replied, or
-            // when the service cannot autofill it (and returned a null response).
-            if (sVerbose) {
-                Slog.v(TAG, "showSaveLocked(): no responses on session");
-            }
-            return true;
-        }
-
-        final int lastResponseIdx = getLastResponseIndexLocked();
-        if (lastResponseIdx < 0) {
-            Slog.w(TAG, "showSaveLocked(): did not get last response. mResponses=" + mResponses
-                    + ", mViewStates=" + mViewStates);
-            return true;
-        }
-
-        final FillResponse response = mResponses.valueAt(lastResponseIdx);
-        final SaveInfo saveInfo = response.getSaveInfo();
-        if (sVerbose) {
-            Slog.v(TAG, "showSaveLocked(): mResponses=" + mResponses + ", mContexts=" + mContexts
-                    + ", mViewStates=" + mViewStates);
-        }
+        final FillResponse response = getLastResponseLocked("showSaveLocked()");
+        final SaveInfo saveInfo = response == null ? null : response.getSaveInfo();
 
         /*
          * The Save dialog is only shown if all conditions below are met:
@@ -845,7 +854,7 @@
 
                 AutofillValue value = viewState.getCurrentValue();
                 if (value == null || value.isEmpty()) {
-                    final AutofillValue initialValue = getValueFromContexts(id);
+                    final AutofillValue initialValue = getValueFromContextsLocked(id);
                     if (initialValue != null) {
                         if (sDebug) {
                             Slog.d(TAG, "Value of required field " + id + " didn't change; "
@@ -899,7 +908,7 @@
                         }
                     } else {
                         // Update current values cache based on initial value
-                        final AutofillValue initialValue = getValueFromContexts(id);
+                        final AutofillValue initialValue = getValueFromContextsLocked(id);
                         if (sDebug) {
                             Slog.d(TAG, "no current value for " + id + "; initial value is "
                                     + initialValue);
@@ -918,15 +927,21 @@
 
                 final InternalValidator validator = saveInfo.getValidator();
                 if (validator != null) {
+                    final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_SAVE_VALIDATION);
                     boolean isValid;
                     try {
                         isValid = validator.isValid(valueFinder);
+                        log.setType(isValid
+                                ? MetricsEvent.TYPE_SUCCESS
+                                : MetricsEvent.TYPE_DISMISS);
                     } catch (Exception e) {
-                        Slog.e(TAG, "Not showing save UI because of exception during validation "
-                                + e.getClass());
+                        Slog.e(TAG, "Not showing save UI because validation failed:", e);
+                        log.setType(MetricsEvent.TYPE_FAILURE);
+                        mMetricsLogger.write(log);
                         return true;
                     }
 
+                    mMetricsLogger.write(log);
                     if (!isValid) {
                         Slog.i(TAG, "not showing save UI because fields failed validation");
                         return true;
@@ -970,11 +985,12 @@
                 }
 
                 if (sDebug) Slog.d(TAG, "Good news, everyone! All checks passed, show save UI!");
-                mService.setSaveShown(id);
+                mService.logSaveShown(id);
                 final IAutoFillManagerClient client = getClient();
-                mPendingSaveUi = new PendingUi(mActivityToken);
-                getUiForShowing().showSaveUi(mService.getServiceLabel(), saveInfo,
-                        valueFinder, mPackageName, this, mPendingSaveUi, id, client);
+                mPendingSaveUi = new PendingUi(mActivityToken, id, client);
+                getUiForShowing().showSaveUi(mService.getServiceLabel(), mService.getServiceIcon(),
+                        mService.getServicePackageName(), saveInfo, valueFinder, mPackageName, this,
+                        mPendingSaveUi);
                 if (client != null) {
                     try {
                         client.setSaveUiState(id, true);
@@ -1006,7 +1022,7 @@
      * Gets the latest non-empty value for the given id in the autofill contexts.
      */
     @Nullable
-    private AutofillValue getValueFromContexts(AutofillId id) {
+    private AutofillValue getValueFromContextsLocked(AutofillId id) {
         final int numContexts = mContexts.size();
         for (int i = numContexts - 1; i >= 0; i--) {
             final FillContext context = mContexts.get(i);
@@ -1028,7 +1044,7 @@
      * Gets the latest autofill options for the given id in the autofill contexts.
      */
     @Nullable
-    private CharSequence[] getAutofillOptionsFromContexts(AutofillId id) {
+    private CharSequence[] getAutofillOptionsFromContextsLocked(AutofillId id) {
         final int numContexts = mContexts.size();
 
         for (int i = numContexts - 1; i >= 0; i--) {
@@ -1053,6 +1069,11 @@
 
         if (sVerbose) Slog.v(TAG, "callSaveLocked(): mViewStates=" + mViewStates);
 
+        if (mContexts == null) {
+            Slog.w(TAG, "callSaveLocked(): no contexts");
+            return;
+        }
+
         final int numContexts = mContexts.size();
 
         for (int contextNum = 0; contextNum < numContexts; contextNum++) {
@@ -1234,6 +1255,21 @@
                 break;
             case ACTION_VALUE_CHANGED:
                 if (value != null && !value.equals(viewState.getCurrentValue())) {
+                    if (value.isEmpty()
+                            && viewState.getCurrentValue() != null
+                            && viewState.getCurrentValue().isText()
+                            && viewState.getCurrentValue().getTextValue() != null
+                            && getSaveInfoLocked() != null) {
+                        final int length = viewState.getCurrentValue().getTextValue().length();
+                        if (sDebug) {
+                            Slog.d(TAG, "updateLocked(" + id + "): resetting value that was "
+                                    + length + " chars long");
+                        }
+                        final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_VALUE_RESET)
+                                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_PREVIOUS_LENGTH, length);
+                        mMetricsLogger.write(log);
+                    }
+
                     // Always update the internal state.
                     viewState.setCurrentValue(value);
 
@@ -1309,7 +1345,8 @@
             filterText = value.getTextValue().toString();
         }
 
-        getUiForShowing().showFillUi(filledId, response, filterText, mPackageName, this);
+        getUiForShowing().showFillUi(filledId, response, filterText,
+                mService.getServicePackageName(), mPackageName, this);
     }
 
     boolean isDestroyed() {
@@ -1324,11 +1361,15 @@
         }
     }
 
-    private void notifyUnavailableToClient() {
+    private void notifyUnavailableToClient(boolean sessionFinished) {
         synchronized (mLock) {
-            if (!mHasCallback || mCurrentViewId == null) return;
+            if (mCurrentViewId == null) return;
             try {
-                mClient.notifyNoFillUi(id, mCurrentViewId);
+                if (mHasCallback) {
+                    mClient.notifyNoFillUi(id, mCurrentViewId, sessionFinished);
+                } else if (sessionFinished) {
+                    mClient.setSessionFinished();
+                }
             } catch (RemoteException e) {
                 Slog.e(TAG, "Error notifying client no fill UI: id=" + mCurrentViewId, e);
             }
@@ -1409,6 +1450,17 @@
         processResponseLocked(newResponse, 0);
     }
 
+    private void processNullResponseLocked(int flags) {
+        if (sVerbose) Slog.v(TAG, "canceling session " + id + " when server returned null");
+        if ((flags & FLAG_MANUAL_REQUEST) != 0) {
+            getUiForShowing().showError(R.string.autofill_error_cannot_autofill, this);
+        }
+        mService.resetLastResponse();
+        // Nothing to be done, but need to notify client.
+        notifyUnavailableToClient(true);
+        removeSelf();
+    }
+
     private void processResponseLocked(@NonNull FillResponse newResponse, int flags) {
         // Make sure we are hiding the UI which will be shown
         // only if handling the current response requires it.
@@ -1523,7 +1575,11 @@
         return viewState;
     }
 
-    void autoFill(int requestId, int datasetIndex, Dataset dataset) {
+    void autoFill(int requestId, int datasetIndex, Dataset dataset, boolean generateEvent) {
+        if (sDebug) {
+            Slog.d(TAG, "autoFill(): requestId=" + requestId  + "; datasetIdx=" + datasetIndex
+                    + "; dataset=" + dataset);
+        }
         synchronized (mLock) {
             if (mDestroyed) {
                 Slog.w(TAG, "Call to Session#autoFill() rejected - session: "
@@ -1532,21 +1588,26 @@
             }
             // Autofill it directly...
             if (dataset.getAuthentication() == null) {
-                mService.setDatasetSelected(dataset.getId(), id);
+                if (generateEvent) {
+                    mService.logDatasetSelected(dataset.getId(), id);
+                }
 
                 autoFillApp(dataset);
                 return;
             }
 
             // ...or handle authentication.
-            mService.setDatasetAuthenticationSelected(dataset.getId(), id);
+            mService.logDatasetAuthenticationSelected(dataset.getId(), id);
             setViewStatesLocked(null, dataset, ViewState.STATE_WAITING_DATASET_AUTH, false);
-            final Intent fillInIntent = createAuthFillInIntent(
-                    getFillContextByRequestIdLocked(requestId).getStructure(), mClientState);
-
+            final Intent fillInIntent = createAuthFillInIntentLocked(requestId, mClientState);
+            if (fillInIntent == null) {
+                forceRemoveSelfLocked();
+                return;
+            }
             final int authenticationId = AutofillManager.makeAuthenticationId(requestId,
                     datasetIndex);
             startAuthentication(authenticationId, dataset.getAuthentication(), fillInIntent);
+
         }
     }
 
@@ -1556,9 +1617,18 @@
         }
     }
 
-    private Intent createAuthFillInIntent(AssistStructure structure, Bundle extras) {
+    // TODO: this should never be null, but we got at least one occurrence, probably due to a race.
+    @Nullable
+    private Intent createAuthFillInIntentLocked(int requestId, Bundle extras) {
         final Intent fillInIntent = new Intent();
-        fillInIntent.putExtra(AutofillManager.EXTRA_ASSIST_STRUCTURE, structure);
+
+        final FillContext context = getFillContextByRequestIdLocked(requestId);
+        if (context == null) {
+            Slog.wtf(TAG, "createAuthFillInIntentLocked(): no FillContext. requestId=" + requestId
+                    + "; mContexts= " + mContexts);
+            return null;
+        }
+        fillInIntent.putExtra(AutofillManager.EXTRA_ASSIST_STRUCTURE, context.getStructure());
         fillInIntent.putExtra(AutofillManager.EXTRA_CLIENT_STATE, extras);
         return fillInIntent;
     }
@@ -1696,10 +1766,10 @@
         if (mDestroyed) {
             return null;
         }
-        mUi.destroyAll(id, getClient(), this);
+        mUi.destroyAll(mPendingSaveUi, this, true);
         mUi.clearCallback(this);
         mDestroyed = true;
-        mMetricsLogger.action(MetricsEvent.AUTOFILL_SESSION_FINISHED, mPackageName);
+        writeLog(MetricsEvent.AUTOFILL_SESSION_FINISHED);
         return mRemoteFillService;
     }
 
@@ -1712,7 +1782,16 @@
 
         mPendingSaveUi = null;
         removeSelfLocked();
-        mUi.destroyAll(id, getClient(), this);
+
+        mHandlerCaller.getHandler().post(() -> {
+            try {
+                mClient.setState(mService.isEnabled(), true, false);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "error updating client state: " + e);
+            }
+        });
+
+        mUi.destroyAll(mPendingSaveUi, this, false);
     }
 
     /**
@@ -1753,7 +1832,8 @@
 
     /**
      * Checks whether this session is hiding the Save UI to handle a custom description link for
-     * a specific {@code token} created by {@link PendingUi#PendingUi(IBinder)}.
+     * a specific {@code token} created by
+     * {@link PendingUi#PendingUi(IBinder, int, IAutoFillManagerClient)}.
      */
     boolean isSaveUiPendingForToken(@NonNull IBinder token) {
         return isSaveUiPending() && token.equals(mPendingSaveUi.getToken());
@@ -1783,4 +1863,16 @@
         }
         return lastResponseIdx;
     }
+
+    private LogMaker newLogMaker(int category) {
+        return newLogMaker(category, mService.getServicePackageName());
+    }
+
+    private LogMaker newLogMaker(int category, String servicePackageName) {
+        return Helper.newLogMaker(category, mPackageName, servicePackageName);
+    }
+
+    private void writeLog(int category) {
+        mMetricsLogger.write(newLogMaker(category));
+    }
 }
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index 7febf83..36b95fc 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -22,6 +22,7 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.IntentSender;
+import android.graphics.drawable.Drawable;
 import android.metrics.LogMaker;
 import android.os.Bundle;
 import android.os.Handler;
@@ -35,13 +36,13 @@
 import android.util.Slog;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillManager;
-import android.view.autofill.IAutoFillManagerClient;
 import android.view.autofill.IAutofillWindowPresenter;
 import android.widget.Toast;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.server.UiThread;
+import com.android.server.autofill.Helper;
 
 import java.io.PrintWriter;
 
@@ -158,21 +159,22 @@
      * @param focusedId the currently focused field
      * @param response the current fill response
      * @param filterText text of the view to be filled
+     * @param servicePackageName package name of the autofill service filling the activity
      * @param packageName package name of the activity that is filled
      * @param callback Identifier for the caller
      */
     public void showFillUi(@NonNull AutofillId focusedId, @NonNull FillResponse response,
-            @Nullable String filterText, @NonNull String packageName,
-            @NonNull AutoFillUiCallback callback) {
+            @Nullable String filterText, @Nullable String servicePackageName,
+            @NonNull String packageName, @NonNull AutoFillUiCallback callback) {
         if (sDebug) {
             final int size = filterText == null ? 0 : filterText.length();
             Slog.d(TAG, "showFillUi(): id=" + focusedId + ", filter=" + size + " chars");
         }
-        final LogMaker log = (new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_FILL_UI))
-                .setPackageName(packageName)
-                .addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_FILTERTEXT_LEN,
+        final LogMaker log =
+                Helper.newLogMaker(MetricsEvent.AUTOFILL_FILL_UI, packageName, servicePackageName)
+                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_FILTERTEXT_LEN,
                         filterText == null ? 0 : filterText.length())
-                .addTaggedData(MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS,
+                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_DATASETS,
                         response.getDatasets() == null ? 0 : response.getDatasets().size());
 
         mHandler.post(() -> {
@@ -184,7 +186,7 @@
                     filterText, mOverlayControl, new FillUi.Callback() {
                 @Override
                 public void onResponsePicked(FillResponse response) {
-                    log.setType(MetricsProto.MetricsEvent.TYPE_DETAIL);
+                    log.setType(MetricsEvent.TYPE_DETAIL);
                     hideFillUiUiThread(callback);
                     if (mCallback != null) {
                         mCallback.authenticate(response.getRequestId(),
@@ -195,7 +197,7 @@
 
                 @Override
                 public void onDatasetPicked(Dataset dataset) {
-                    log.setType(MetricsProto.MetricsEvent.TYPE_ACTION);
+                    log.setType(MetricsEvent.TYPE_ACTION);
                     hideFillUiUiThread(callback);
                     if (mCallback != null) {
                         final int datasetIndex = response.getDatasets().indexOf(dataset);
@@ -205,14 +207,14 @@
 
                 @Override
                 public void onCanceled() {
-                    log.setType(MetricsProto.MetricsEvent.TYPE_DISMISS);
+                    log.setType(MetricsEvent.TYPE_DISMISS);
                     hideFillUiUiThread(callback);
                 }
 
                 @Override
                 public void onDestroy() {
-                    if (log.getType() == MetricsProto.MetricsEvent.TYPE_UNKNOWN) {
-                        log.setType(MetricsProto.MetricsEvent.TYPE_CLOSE);
+                    if (log.getType() == MetricsEvent.TYPE_UNKNOWN) {
+                        log.setType(MetricsEvent.TYPE_CLOSE);
                     }
                     mMetricsLogger.write(log);
                 }
@@ -245,39 +247,40 @@
     /**
      * Shows the UI asking the user to save for autofill.
      */
-    public void showSaveUi(@NonNull CharSequence providerLabel, @NonNull SaveInfo info,
+    public void showSaveUi(@NonNull CharSequence serviceLabel, @NonNull Drawable serviceIcon,
+            @Nullable String servicePackageName, @NonNull SaveInfo info,
             @NonNull ValueFinder valueFinder, @NonNull String packageName,
-            @NonNull AutoFillUiCallback callback, @NonNull PendingUi pendingUi,
-            int sessionId, @Nullable IAutoFillManagerClient client) {
+            @NonNull AutoFillUiCallback callback, @NonNull PendingUi pendingSaveUi) {
         if (sVerbose) Slog.v(TAG, "showSaveUi() for " + packageName + ": " + info);
         int numIds = 0;
         numIds += info.getRequiredIds() == null ? 0 : info.getRequiredIds().length;
         numIds += info.getOptionalIds() == null ? 0 : info.getOptionalIds().length;
 
-        LogMaker log = (new LogMaker(MetricsProto.MetricsEvent.AUTOFILL_SAVE_UI))
-                .setPackageName(packageName).addTaggedData(
-                        MetricsProto.MetricsEvent.FIELD_AUTOFILL_NUM_IDS, numIds);
+        final LogMaker log =
+                Helper.newLogMaker(MetricsEvent.AUTOFILL_SAVE_UI, packageName, servicePackageName)
+                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_NUM_IDS, numIds);
 
         mHandler.post(() -> {
             if (callback != mCallback) {
                 return;
             }
             hideAllUiThread(callback);
-            mSaveUi = new SaveUi(mContext, pendingUi, providerLabel, info, valueFinder,
-                    mOverlayControl, client, new SaveUi.OnSaveListener() {
+            mSaveUi = new SaveUi(mContext, pendingSaveUi, serviceLabel, serviceIcon,
+                    servicePackageName, packageName, info, valueFinder, mOverlayControl,
+                    new SaveUi.OnSaveListener() {
                 @Override
                 public void onSave() {
-                    log.setType(MetricsProto.MetricsEvent.TYPE_ACTION);
+                    log.setType(MetricsEvent.TYPE_ACTION);
                     hideSaveUiUiThread(mCallback);
                     if (mCallback != null) {
                         mCallback.save();
                     }
-                    destroySaveUiUiThread(sessionId, client);
+                    destroySaveUiUiThread(pendingSaveUi, true);
                 }
 
                 @Override
                 public void onCancel(IntentSender listener) {
-                    log.setType(MetricsProto.MetricsEvent.TYPE_DISMISS);
+                    log.setType(MetricsEvent.TYPE_DISMISS);
                     hideSaveUiUiThread(mCallback);
                     if (listener != null) {
                         try {
@@ -290,13 +293,13 @@
                     if (mCallback != null) {
                         mCallback.cancelSave();
                     }
-                    destroySaveUiUiThread(sessionId, client);
+                    destroySaveUiUiThread(pendingSaveUi, true);
                 }
 
                 @Override
                 public void onDestroy() {
-                    if (log.getType() == MetricsProto.MetricsEvent.TYPE_UNKNOWN) {
-                        log.setType(MetricsProto.MetricsEvent.TYPE_CLOSE);
+                    if (log.getType() == MetricsEvent.TYPE_UNKNOWN) {
+                        log.setType(MetricsEvent.TYPE_CLOSE);
 
                         if (mCallback != null) {
                             mCallback.cancelSave();
@@ -331,9 +334,9 @@
     /**
      * Destroy all UI affordances.
      */
-    public void destroyAll(int sessionId, @Nullable IAutoFillManagerClient client,
-            @Nullable AutoFillUiCallback callback) {
-        mHandler.post(() -> destroyAllUiThread(sessionId, client, callback));
+    public void destroyAll(@Nullable PendingUi pendingSaveUi,
+            @Nullable AutoFillUiCallback callback, boolean notifyClient) {
+        mHandler.post(() -> destroyAllUiThread(pendingSaveUi, callback, notifyClient));
     }
 
     public void dump(PrintWriter pw) {
@@ -363,18 +366,20 @@
     }
 
     @android.annotation.UiThread
-    private void hideSaveUiUiThread(@Nullable AutoFillUiCallback callback) {
+    @Nullable
+    private PendingUi hideSaveUiUiThread(@Nullable AutoFillUiCallback callback) {
         if (sVerbose) {
             Slog.v(TAG, "hideSaveUiUiThread(): mSaveUi=" + mSaveUi + ", callback=" + callback
                     + ", mCallback=" + mCallback);
         }
         if (mSaveUi != null && (callback == null || callback == mCallback)) {
-            mSaveUi.hide();
+            return mSaveUi.hide();
         }
+        return null;
     }
 
     @android.annotation.UiThread
-    private void destroySaveUiUiThread(int sessionId, @Nullable IAutoFillManagerClient client) {
+    private void destroySaveUiUiThread(@Nullable PendingUi pendingSaveUi, boolean notifyClient) {
         if (mSaveUi == null) {
             // Calling destroySaveUiUiThread() twice is normal - it usually happens when the
             // first call is made after the SaveUI is hidden and the second when the session is
@@ -383,13 +388,13 @@
             return;
         }
 
-        if (sDebug) Slog.d(TAG, "destroySaveUiUiThread(): id=" + sessionId);
+        if (sDebug) Slog.d(TAG, "destroySaveUiUiThread(): " + pendingSaveUi);
         mSaveUi.destroy();
         mSaveUi = null;
-        if (client != null) {
+        if (pendingSaveUi != null && notifyClient) {
             try {
                 if (sDebug) Slog.d(TAG, "destroySaveUiUiThread(): notifying client");
-                client.setSaveUiState(sessionId, false);
+                pendingSaveUi.client.setSaveUiState(pendingSaveUi.id, false);
             } catch (RemoteException e) {
                 Slog.e(TAG, "Error notifying client to set save UI state to hidden: " + e);
             }
@@ -397,15 +402,22 @@
     }
 
     @android.annotation.UiThread
-    private void destroyAllUiThread(int sessionId, @Nullable IAutoFillManagerClient client,
-            @Nullable AutoFillUiCallback callback) {
+    private void destroyAllUiThread(@Nullable PendingUi pendingSaveUi,
+            @Nullable AutoFillUiCallback callback, boolean notifyClient) {
         hideFillUiUiThread(callback);
-        destroySaveUiUiThread(sessionId, client);
+        destroySaveUiUiThread(pendingSaveUi, notifyClient);
     }
 
     @android.annotation.UiThread
     private void hideAllUiThread(@Nullable AutoFillUiCallback callback) {
         hideFillUiUiThread(callback);
-        hideSaveUiUiThread(callback);
+        final PendingUi pendingSaveUi = hideSaveUiUiThread(callback);
+        if (pendingSaveUi != null && pendingSaveUi.getState() == PendingUi.STATE_FINISHED) {
+            if (sDebug) {
+                Slog.d(TAG, "hideAllUiThread(): "
+                        + "destroying Save UI because pending restoration is finished");
+            }
+            destroySaveUiUiThread(pendingSaveUi, true);
+        }
     }
 }
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index 24f3b33..371e74d 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -229,6 +229,13 @@
     public void setFilterText(@Nullable String filterText) {
         throwIfDestroyed();
         if (mAdapter == null) {
+            // ViewState doesn't not support filtering - typically when it's for an authenticated
+            // FillResponse.
+            if (TextUtils.isEmpty(filterText)) {
+                mCallback.requestShowFillUi(mContentWidth, mContentHeight, mWindowPresenter);
+            } else {
+                mCallback.requestHideFillUi();
+            }
             return;
         }
 
@@ -510,8 +517,9 @@
                         final ViewItem item = mAllItems.get(i);
                         final String value = item.getValue();
                         // No value, i.e. null, matches any filter
-                        if (value == null
-                                || value.toLowerCase().startsWith(constraintLowerCase)) {
+                        if ((value == null && item.mDataset.getAuthentication() == null)
+                                || (value != null
+                                        && value.toLowerCase().startsWith(constraintLowerCase))) {
                             filteredItems.add(item);
                         }
                     }
@@ -525,9 +533,11 @@
                     final boolean resultCountChanged;
                     final int oldItemCount = mFilteredItems.size();
                     mFilteredItems.clear();
-                    @SuppressWarnings("unchecked")
-                    final List<ViewItem> items = (List<ViewItem>) results.values;
-                    mFilteredItems.addAll(items);
+                    if (results.count > 0) {
+                        @SuppressWarnings("unchecked")
+                        final List<ViewItem> items = (List<ViewItem>) results.values;
+                        mFilteredItems.addAll(items);
+                    }
                     resultCountChanged = (oldItemCount != mFilteredItems.size());
                     if (resultCountChanged) {
                         announceSearchResultIfNeeded();
diff --git a/services/autofill/java/com/android/server/autofill/ui/PendingUi.java b/services/autofill/java/com/android/server/autofill/ui/PendingUi.java
index 87263ed..0851d3b 100644
--- a/services/autofill/java/com/android/server/autofill/ui/PendingUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/PendingUi.java
@@ -18,6 +18,7 @@
 import android.annotation.NonNull;
 import android.os.IBinder;
 import android.util.DebugUtils;
+import android.view.autofill.IAutoFillManagerClient;
 
 /**
  * Helper class used to handle a pending Autofill affordance such as the Save UI.
@@ -34,15 +35,19 @@
 
     private final IBinder mToken;
     private int mState;
+    public final int id;
+    public final IAutoFillManagerClient client;
 
     /**
      * Default constructor.
      *
      * @param token token used to identify this pending UI.
      */
-    public PendingUi(@NonNull IBinder token) {
+    public PendingUi(@NonNull IBinder token, int id, @NonNull IAutoFillManagerClient client) {
         mToken = token;
         mState = STATE_CREATED;
+        this.id = id;
+        this.client = client;
     }
 
     /**
@@ -76,7 +81,7 @@
 
     @Override
     public String toString() {
-        return "PendingUi: [token=" + mToken + ", state="
+        return "PendingUi: [token=" + mToken + ", id=" + id + ", state="
                 + DebugUtils.flagsToString(PendingUi.class, "STATE_", mState) + "]";
     }
 }
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index 67c1b8c..32f4d69 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -20,12 +20,15 @@
 import static com.android.server.autofill.Helper.sVerbose;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.Dialog;
 import android.app.PendingIntent;
-import android.app.PendingIntent.CanceledException;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.metrics.LogMaker;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -43,12 +46,14 @@
 import android.view.Window;
 import android.view.WindowManager;
 import android.view.autofill.AutofillManager;
-import android.view.autofill.IAutoFillManagerClient;
+import android.widget.ImageView;
 import android.widget.RemoteViews;
 import android.widget.ScrollView;
 import android.widget.TextView;
 
 import com.android.internal.R;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.server.UiThread;
 
 import java.io.PrintWriter;
@@ -107,6 +112,7 @@
     }
 
     private final Handler mHandler = UiThread.getHandler();
+    private final MetricsLogger mMetricsLogger = new MetricsLogger();
 
     private final @NonNull Dialog mDialog;
 
@@ -117,16 +123,21 @@
     private final CharSequence mTitle;
     private final CharSequence mSubTitle;
     private final PendingUi mPendingUi;
+    private final String mServicePackageName;
+    private final String mPackageName;
 
     private boolean mDestroyed;
 
     SaveUi(@NonNull Context context, @NonNull PendingUi pendingUi,
-           @NonNull CharSequence providerLabel, @NonNull SaveInfo info,
-           @NonNull ValueFinder valueFinder, @NonNull OverlayControl overlayControl,
-           @NonNull IAutoFillManagerClient client, @NonNull OnSaveListener listener) {
+           @NonNull CharSequence serviceLabel, @NonNull Drawable serviceIcon,
+           @Nullable String servicePackageName, @NonNull String packageName,
+           @NonNull SaveInfo info, @NonNull ValueFinder valueFinder,
+           @NonNull OverlayControl overlayControl, @NonNull OnSaveListener listener) {
         mPendingUi= pendingUi;
         mListener = new OneTimeListener(listener);
         mOverlayControl = overlayControl;
+        mServicePackageName = servicePackageName;
+        mPackageName = packageName;
 
         final LayoutInflater inflater = LayoutInflater.from(context);
         final View view = inflater.inflate(R.layout.autofill_save, null);
@@ -155,27 +166,30 @@
         switch (types.size()) {
             case 1:
                 mTitle = Html.fromHtml(context.getString(R.string.autofill_save_title_with_type,
-                        types.valueAt(0), providerLabel), 0);
+                        types.valueAt(0), serviceLabel), 0);
                 break;
             case 2:
                 mTitle = Html.fromHtml(context.getString(R.string.autofill_save_title_with_2types,
-                        types.valueAt(0), types.valueAt(1), providerLabel), 0);
+                        types.valueAt(0), types.valueAt(1), serviceLabel), 0);
                 break;
             case 3:
                 mTitle = Html.fromHtml(context.getString(R.string.autofill_save_title_with_3types,
-                        types.valueAt(0), types.valueAt(1), types.valueAt(2), providerLabel), 0);
+                        types.valueAt(0), types.valueAt(1), types.valueAt(2), serviceLabel), 0);
                 break;
             default:
                 // Use generic if more than 3 or invalid type (size 0).
                 mTitle = Html.fromHtml(
-                        context.getString(R.string.autofill_save_title, providerLabel), 0);
+                        context.getString(R.string.autofill_save_title, serviceLabel), 0);
         }
-
         titleView.setText(mTitle);
 
+        setServiceIcon(context, view, serviceIcon);
+
         ScrollView subtitleContainer = null;
         final CustomDescription customDescription = info.getCustomDescription();
         if (customDescription != null) {
+            writeLog(MetricsEvent.AUTOFILL_SAVE_CUSTOM_DESCRIPTION, type);
+
             mSubTitle = null;
             if (sDebug) Slog.d(TAG, "Using custom description");
 
@@ -185,40 +199,35 @@
                     @Override
                     public boolean onClickHandler(View view, PendingIntent pendingIntent,
                             Intent intent) {
+                        final LogMaker log =
+                                newLogMaker(MetricsEvent.AUTOFILL_SAVE_LINK_TAPPED, type);
                         // We need to hide the Save UI before launching the pending intent, and
                         // restore back it once the activity is finished, and that's achieved by
                         // adding a custom extra in the activity intent.
-                        if (pendingIntent != null) {
-                            if (intent == null) {
-                                Slog.w(TAG,
-                                        "remote view on custom description does not have intent");
-                                return false;
-                            }
-                            if (!pendingIntent.isActivity()) {
-                                Slog.w(TAG, "ignoring custom description pending intent that's not "
-                                        + "for an activity: " + pendingIntent);
-                                return false;
-                            }
-                            if (sVerbose) {
-                                Slog.v(TAG,
-                                        "Intercepting custom description intent: " + intent);
-                            }
-                            final IBinder token = mPendingUi.getToken();
-                            intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token);
-                            try {
-                                client.startIntentSender(pendingIntent.getIntentSender(),
-                                        intent);
-                                mPendingUi.setState(PendingUi.STATE_PENDING);
-                                if (sDebug) {
-                                    Slog.d(TAG, "hiding UI until restored with token " + token);
-                                }
-                                hide();
-                            } catch (RemoteException e) {
-                                Slog.w(TAG, "error triggering pending intent: " + intent);
-                                return false;
-                            }
+                        final boolean isValid = isValidLink(pendingIntent, intent);
+                        if (!isValid) {
+                            log.setType(MetricsEvent.TYPE_UNKNOWN);
+                            mMetricsLogger.write(log);
+                            return false;
                         }
-                        return true;
+                        if (sVerbose) Slog.v(TAG, "Intercepting custom description intent");
+                        final IBinder token = mPendingUi.getToken();
+                        intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token);
+                        try {
+                            pendingUi.client.startIntentSender(pendingIntent.getIntentSender(),
+                                    intent);
+                            mPendingUi.setState(PendingUi.STATE_PENDING);
+                            if (sDebug) Slog.d(TAG, "hiding UI until restored with token " + token);
+                            hide();
+                            log.setType(MetricsEvent.TYPE_OPEN);
+                            mMetricsLogger.write(log);
+                            return true;
+                        } catch (RemoteException e) {
+                            Slog.w(TAG, "error triggering pending intent: " + intent);
+                            log.setType(MetricsEvent.TYPE_FAILURE);
+                            mMetricsLogger.write(log);
+                            return false;
+                        }
                     }
                 };
 
@@ -236,6 +245,7 @@
         } else {
             mSubTitle = info.getDescription();
             if (mSubTitle != null) {
+                writeLog(MetricsEvent.AUTOFILL_SAVE_CUSTOM_SUBTITLE, type);
                 subtitleContainer = view.findViewById(R.id.autofill_save_custom_subtitle);
                 final TextView subtitleView = new TextView(context);
                 subtitleView.setText(mSubTitle);
@@ -284,6 +294,61 @@
         show();
     }
 
+    private void setServiceIcon(Context context, View view, Drawable serviceIcon) {
+        final ImageView iconView = view.findViewById(R.id.autofill_save_icon);
+        final Resources res = context.getResources();
+
+        final int maxWidth = res.getDimensionPixelSize(R.dimen.autofill_save_icon_max_size);
+        final int maxHeight = maxWidth;
+        final int actualWidth = serviceIcon.getMinimumWidth();
+        final int actualHeight = serviceIcon.getMinimumHeight();
+
+        if (actualWidth <= maxWidth && actualHeight <= maxHeight) {
+            if (sDebug) {
+                Slog.d(TAG, "Addingservice icon "
+                        + "(" + actualWidth + "x" + actualHeight + ") as it's less than maximum "
+                        + "(" + maxWidth + "x" + maxHeight + ").");
+            }
+            iconView.setImageDrawable(serviceIcon);
+        } else {
+            Slog.w(TAG, "Not adding service icon of size "
+                    + "(" + actualWidth + "x" + actualHeight + ") because maximum is "
+                    + "(" + maxWidth + "x" + maxHeight + ").");
+            ((ViewGroup)iconView.getParent()).removeView(iconView);
+        }
+    }
+
+    private static boolean isValidLink(PendingIntent pendingIntent, Intent intent) {
+        if (pendingIntent == null) {
+            Slog.w(TAG, "isValidLink(): custom description without pending intent");
+            return false;
+        }
+        if (!pendingIntent.isActivity()) {
+            Slog.w(TAG, "isValidLink(): pending intent not for activity");
+            return false;
+        }
+        if (intent == null) {
+            Slog.w(TAG, "isValidLink(): no intent");
+            return false;
+        }
+        return true;
+    }
+
+    private LogMaker newLogMaker(int category, int saveType) {
+        return newLogMaker(category)
+                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SAVE_TYPE, saveType);
+    }
+
+    private LogMaker newLogMaker(int category) {
+        return new LogMaker(category)
+                .setPackageName(mPackageName)
+                .addTaggedData(MetricsEvent.FIELD_AUTOFILL_SERVICE, mServicePackageName);
+    }
+
+    private void writeLog(int category, int saveType) {
+        mMetricsLogger.write(newLogMaker(category, saveType));
+    }
+
     /**
      * Update the pending UI, if any.
      *
@@ -297,17 +362,25 @@
                     + mPendingUi.getToken());
             return;
         }
-        switch (operation) {
-            case AutofillManager.PENDING_UI_OPERATION_RESTORE:
-                if (sDebug) Slog.d(TAG, "Restoring save dialog for " + token);
-                show();
-                break;
-            case AutofillManager.PENDING_UI_OPERATION_CANCEL:
-                if (sDebug) Slog.d(TAG, "Cancelling pending save dialog for " + token);
-                hide();
-                break;
-            default:
-                Slog.w(TAG, "restore(): invalid operation " + operation);
+        final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_PENDING_SAVE_UI_OPERATION);
+        try {
+            switch (operation) {
+                case AutofillManager.PENDING_UI_OPERATION_RESTORE:
+                    if (sDebug) Slog.d(TAG, "Restoring save dialog for " + token);
+                    log.setType(MetricsEvent.TYPE_OPEN);
+                    show();
+                    break;
+                case AutofillManager.PENDING_UI_OPERATION_CANCEL:
+                    log.setType(MetricsEvent.TYPE_DISMISS);
+                    if (sDebug) Slog.d(TAG, "Cancelling pending save dialog for " + token);
+                    hide();
+                    break;
+                default:
+                    log.setType(MetricsEvent.TYPE_FAILURE);
+                    Slog.w(TAG, "restore(): invalid operation " + operation);
+            }
+        } finally {
+            mMetricsLogger.write(log);
         }
         mPendingUi.setState(PendingUi.STATE_FINISHED);
     }
@@ -318,13 +391,14 @@
         mOverlayControl.hideOverlays();
    }
 
-    void hide() {
+    PendingUi hide() {
         if (sVerbose) Slog.v(TAG, "Hiding save dialog.");
         try {
             mDialog.hide();
         } finally {
             mOverlayControl.showOverlays();
         }
+        return mPendingUi;
     }
 
     void destroy() {
@@ -355,6 +429,8 @@
         pw.print(prefix); pw.print("title: "); pw.println(mTitle);
         pw.print(prefix); pw.print("subtitle: "); pw.println(mSubTitle);
         pw.print(prefix); pw.print("pendingUi: "); pw.println(mPendingUi);
+        pw.print(prefix); pw.print("service: "); pw.println(mServicePackageName);
+        pw.print(prefix); pw.print("app: "); pw.println(mPackageName);
 
         final View view = mDialog.getWindow().getDecorView();
         final int[] loc = view.getLocationOnScreen();
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 92d3d39..edcd4b7 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -4535,7 +4535,7 @@
                     }
                     mOutputFile.close();
                 } catch (IOException e) {
-                    /* nothing we can do about this */
+                    Slog.e(TAG, "IO error closing adb backup file: " + e.getMessage());
                 }
                 synchronized (mLatch) {
                     mLatch.set(true);
@@ -10112,7 +10112,7 @@
             try {
                 fd.close();
             } catch (IOException e) {
-                // just eat it
+                Slog.e(TAG, "IO error closing output for adb backup: " + e.getMessage());
             }
             Binder.restoreCallingIdentity(oldId);
             Slog.d(TAG, "Adb backup processing complete.");
diff --git a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
index e8c5058..7485977 100644
--- a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
@@ -2486,7 +2486,7 @@
             try {
                 fd.close();
             } catch (IOException e) {
-                // just eat it
+                Slog.e(TAG, "IO error closing output for adb backup: " + e.getMessage());
             }
             Binder.restoreCallingIdentity(oldId);
             Slog.d(TAG, "Adb backup processing complete.");
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
index 804e92c..4085f63 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
@@ -459,7 +459,7 @@
                 }
                 mOutputFile.close();
             } catch (IOException e) {
-                /* nothing we can do about this */
+                Slog.e(TAG, "IO error closing adb backup file: " + e.getMessage());
             }
             synchronized (mLatch) {
                 mLatch.set(true);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 04b2112..e70a294 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -4343,11 +4343,13 @@
             int currentScore, NetworkMisc networkMisc) {
         enforceConnectivityInternalPermission();
 
+        LinkProperties lp = new LinkProperties(linkProperties);
+        lp.ensureDirectlyConnectedRoutes();
         // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
         // satisfies mDefaultRequest.
         final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
-                new Network(reserveNetId()), new NetworkInfo(networkInfo), new LinkProperties(
-                linkProperties), new NetworkCapabilities(networkCapabilities), currentScore,
+                new Network(reserveNetId()), new NetworkInfo(networkInfo), lp,
+                new NetworkCapabilities(networkCapabilities), currentScore,
                 mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest, this);
         synchronized (this) {
             nai.networkMonitor.systemReady = mSystemReady;
@@ -4647,7 +4649,8 @@
             // Ignore updates for disconnected networks
             return;
         }
-
+        // newLp is already a defensive copy.
+        newLp.ensureDirectlyConnectedRoutes();
         if (VDBG) {
             log("Update of LinkProperties for " + nai.name() +
                     "; created=" + nai.created +
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 16f4d04..05c7504 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -403,7 +403,9 @@
     private final BroadcastReceiver mInteractivityReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            updateInteractivityLocked();
+            synchronized (DeviceIdleController.this) {
+                updateInteractivityLocked();
+            }
         }
     };
 
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index e0cde72..90ad8a5 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2162,6 +2162,15 @@
             }
         }
 
+        if (r.fgRequired) {
+            if (DEBUG_FOREGROUND_SERVICE) {
+                Slog.v(TAG, "Whitelisting " + UserHandle.formatUid(r.appInfo.uid)
+                        + " for fg-service launch");
+            }
+            mAm.tempWhitelistUidLocked(r.appInfo.uid,
+                    SERVICE_START_FOREGROUND_TIMEOUT, "fg-service-launch");
+        }
+
         if (!mPendingServices.contains(r)) {
             mPendingServices.add(r);
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index dad3125..cbfc747 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -713,7 +713,7 @@
 
     public boolean canShowErrorDialogs() {
         return mShowDialogs && !mSleeping && !mShuttingDown
-                && !mKeyguardController.isKeyguardShowing()
+                && !mKeyguardController.isKeyguardShowing(DEFAULT_DISPLAY)
                 && !(UserManager.isDeviceInDemoMode(mContext)
                         && mUserController.getCurrentUser().isDemo());
     }
@@ -7005,7 +7005,7 @@
                 mProfileProc = app;
                 profilerInfo = (mProfilerInfo != null && mProfilerInfo.profileFile != null) ?
                         new ProfilerInfo(mProfilerInfo) : null;
-                agent = profilerInfo.agent;
+                agent = mProfilerInfo != null ? mProfilerInfo.agent : null;
             } else if (app.instr != null && app.instr.mProfileFile != null) {
                 profilerInfo = new ProfilerInfo(app.instr.mProfileFile, null, 0, false, false,
                         null);
@@ -12463,19 +12463,14 @@
 
     void onWakefulnessChanged(int wakefulness) {
         synchronized(this) {
+            boolean wasAwake = mWakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE;
+            boolean isAwake = wakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE;
             mWakefulness = wakefulness;
 
-            // Also update state in a special way for running foreground services UI.
-            switch (mWakefulness) {
-                case PowerManagerInternal.WAKEFULNESS_ASLEEP:
-                case PowerManagerInternal.WAKEFULNESS_DREAMING:
-                case PowerManagerInternal.WAKEFULNESS_DOZING:
-                    mServices.updateScreenStateLocked(false /* screenOn */);
-                    break;
-                case PowerManagerInternal.WAKEFULNESS_AWAKE:
-                default:
-                    mServices.updateScreenStateLocked(true /* screenOn */);
-                    break;
+            if (wasAwake != isAwake) {
+                // Also update state in a special way for running foreground services UI.
+                mServices.updateScreenStateLocked(isAwake);
+                sendNotifyVrManagerOfSleepState(!isAwake);
             }
         }
     }
@@ -12511,7 +12506,6 @@
             }
             mStackSupervisor.applySleepTokensLocked(true /* applyToStacks */);
             if (wasSleeping) {
-                sendNotifyVrManagerOfSleepState(false);
                 updateOomAdjLocked();
             }
         } else if (!mSleeping && shouldSleep) {
@@ -12521,7 +12515,6 @@
             }
             mTopProcessState = ActivityManager.PROCESS_STATE_TOP_SLEEPING;
             mStackSupervisor.goingToSleepLocked();
-            sendNotifyVrManagerOfSleepState(true);
             updateOomAdjLocked();
         }
     }
@@ -12615,7 +12608,7 @@
     }
 
     @Override
-    public void setLockScreenShown(boolean showing) {
+    public void setLockScreenShown(boolean showing, int secondaryDisplayShowing) {
         if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER)
                 != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Requires permission "
@@ -12625,7 +12618,7 @@
         synchronized(this) {
             long ident = Binder.clearCallingIdentity();
             try {
-                mKeyguardController.setKeyguardShown(showing);
+                mKeyguardController.setKeyguardShown(showing, secondaryDisplayShowing);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -13231,7 +13224,6 @@
                 return;
             }
         }
-
         // We are now ready to launch the assist activity.
         IResultReceiver sendReceiver = null;
         Bundle sendBundle = null;
@@ -13261,17 +13253,24 @@
             return;
         }
 
-        long ident = Binder.clearCallingIdentity();
+        final long ident = Binder.clearCallingIdentity();
         try {
-            pae.intent.replaceExtras(pae.extras);
-            pae.intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                    | Intent.FLAG_ACTIVITY_SINGLE_TOP
-                    | Intent.FLAG_ACTIVITY_CLEAR_TOP);
-            closeSystemDialogs("assist");
-            try {
-                mContext.startActivityAsUser(pae.intent, new UserHandle(pae.userHandle));
-            } catch (ActivityNotFoundException e) {
-                Slog.w(TAG, "No activity to handle assist action.", e);
+            if (TextUtils.equals(pae.intent.getAction(),
+                    android.service.voice.VoiceInteractionService.SERVICE_INTERFACE)) {
+                pae.intent.putExtras(pae.extras);
+                mContext.startServiceAsUser(pae.intent, new UserHandle(pae.userHandle));
+            } else {
+                pae.intent.replaceExtras(pae.extras);
+                pae.intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                        | Intent.FLAG_ACTIVITY_SINGLE_TOP
+                        | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+                closeSystemDialogs("assist");
+
+                try {
+                    mContext.startActivityAsUser(pae.intent, new UserHandle(pae.userHandle));
+                } catch (ActivityNotFoundException e) {
+                    Slog.w(TAG, "No activity to handle assist action.", e);
+                }
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -14040,10 +14039,10 @@
                 mContext.getPackageManager().hasSystemFeature(FEATURE_FREEFORM_WINDOW_MANAGEMENT)
                         || Settings.Global.getInt(
                                 resolver, DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0;
-        final boolean supportsPictureInPicture =
-                mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
 
         final boolean supportsMultiWindow = ActivityManager.supportsMultiWindow(mContext);
+        final boolean supportsPictureInPicture = supportsMultiWindow &&
+                mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
         final boolean supportsSplitScreenMultiWindow =
                 ActivityManager.supportsSplitScreenMultiWindow(mContext);
         final boolean supportsMultiDisplay = mContext.getPackageManager()
@@ -24082,7 +24081,7 @@
         @Override
         public void notifyKeyguardTrustedChanged() {
             synchronized (ActivityManagerService.this) {
-                if (mKeyguardController.isKeyguardShowing()) {
+                if (mKeyguardController.isKeyguardShowing(DEFAULT_DISPLAY)) {
                     mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
                 }
             }
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 5b27c9c..b2bbf19 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1176,8 +1176,15 @@
      *         can be put a secondary screen.
      */
     boolean canBeLaunchedOnDisplay(int displayId) {
+        final TaskRecord task = getTask();
+
+        // The resizeability of an Activity's parent task takes precendence over the ActivityInfo.
+        // This allows for a non resizable activity to be launched into a resizeable task.
+        final boolean resizeable =
+                task != null ? task.isResizeable() : supportsResizeableMultiWindow();
+
         return service.mStackSupervisor.canPlaceEntityOnDisplay(displayId,
-                supportsResizeableMultiWindow(), launchedFromPid, launchedFromUid, info);
+                resizeable, launchedFromPid, launchedFromUid, info);
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index d62d935..a0817c4 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1980,7 +1980,8 @@
     boolean checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible,
             boolean isTop) {
         final boolean isInPinnedStack = r.getStack().getStackId() == PINNED_STACK_ID;
-        final boolean keyguardShowing = mStackSupervisor.mKeyguardController.isKeyguardShowing();
+        final boolean keyguardShowing = mStackSupervisor.mKeyguardController.isKeyguardShowing(
+                mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY);
         final boolean keyguardLocked = mStackSupervisor.mKeyguardController.isKeyguardLocked();
         final boolean showWhenLocked = r.canShowWhenLocked() && !isInPinnedStack;
         final boolean dismissKeyguard = r.hasDismissKeyguardWindows();
@@ -3007,13 +3008,6 @@
             // Ensure the task/activity being brought forward is not the assistant
             return false;
         }
-        final boolean isFullscreen = toFrontTask != null
-                ? toFrontTask.containsOnlyFullscreenActivities()
-                : toFrontActivity.fullscreen;
-        if (!isFullscreen) {
-            // Ensure the task/activity being brought forward is fullscreen
-            return false;
-        }
         return true;
     }
 
@@ -5212,8 +5206,8 @@
                 voiceInteractor, type);
         // add the task to stack first, mTaskPositioner might need the stack association
         addTask(task, toTop, "createTaskRecord");
-        final boolean isLockscreenShown =
-                mService.mStackSupervisor.mKeyguardController.isKeyguardShowing();
+        final boolean isLockscreenShown = mService.mStackSupervisor.mKeyguardController
+                .isKeyguardShowing(mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY);
         if (!layoutTaskInStack(task, info.windowLayout) && mBounds != null && task.isResizeable()
                 && !isLockscreenShown) {
             task.updateOverrideConfiguration(mBounds);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 7bbc6cc..ab6e602 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1705,6 +1705,9 @@
             return true;
         }
 
+        // Check if caller is already present on display
+        final boolean uidPresentOnDisplay = activityDisplay.isUidPresent(callingUid);
+
         final int displayOwnerUid = activityDisplay.mDisplay.getOwnerUid();
         if (activityDisplay.mDisplay.getType() == TYPE_VIRTUAL && displayOwnerUid != SYSTEM_UID
                 && displayOwnerUid != aInfo.applicationInfo.uid) {
@@ -1717,7 +1720,7 @@
             }
             // Check if the caller is allowed to embed activities from other apps.
             if (mService.checkPermission(ACTIVITY_EMBEDDING, callingPid, callingUid)
-                    == PERMISSION_DENIED) {
+                    == PERMISSION_DENIED && !uidPresentOnDisplay) {
                 if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:"
                         + " disallow activity embedding without permission.");
                 return false;
@@ -1738,8 +1741,7 @@
             return true;
         }
 
-        // Check if caller is present on display
-        if (activityDisplay.isUidPresent(callingUid)) {
+        if (uidPresentOnDisplay) {
             if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check:"
                     + " allow launch for caller present on the display");
             return true;
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index 118484b..8af1f3e 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -264,6 +264,10 @@
                 mStats.updateKernelMemoryBandwidthLocked();
             }
 
+            if ((updateFlags & UPDATE_RPM) != 0) {
+                mStats.updateRpmStatsLocked();
+            }
+
             if (bluetoothInfo != null) {
                 if (bluetoothInfo.isValid()) {
                     mStats.updateBluetoothStateLocked(bluetoothInfo);
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 33568cd..fae215f 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -49,6 +49,7 @@
 import com.android.internal.os.BatteryStatsHelper;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.internal.os.PowerProfile;
+import com.android.internal.os.RpmStats;
 import com.android.internal.util.DumpUtils;
 import com.android.server.LocalServices;
 import com.android.server.power.BatterySaverPolicy.ServiceType;
@@ -84,6 +85,7 @@
     private final Context mContext;
     private final BatteryExternalStatsWorker mWorker;
 
+    private native void getLowPowerStats(RpmStats rpmStats);
     private native int getPlatformLowPowerStats(ByteBuffer outBuffer);
     private native int getSubsystemLowPowerStats(ByteBuffer outBuffer);
     private CharsetDecoder mDecoderStat = StandardCharsets.UTF_8
@@ -95,6 +97,19 @@
     private CharBuffer mUtf16BufferStat = CharBuffer.allocate(MAX_LOW_POWER_STATS_SIZE);
     private static final int MAX_LOW_POWER_STATS_SIZE = 512;
 
+    /**
+     * Replaces the information in the given rpmStats with up-to-date information.
+     */
+    @Override
+    public void fillLowPowerStats(RpmStats rpmStats) {
+        if (DBG) Slog.d(TAG, "begin getLowPowerStats");
+        try {
+            getLowPowerStats(rpmStats);
+        } finally {
+            if (DBG) Slog.d(TAG, "end getLowPowerStats");
+        }
+    }
+
     @Override
     public String getPlatformLowPowerStats() {
         if (DBG) Slog.d(TAG, "begin getPlatformLowPowerStats");
@@ -119,7 +134,7 @@
 
     @Override
     public String getSubsystemLowPowerStats() {
-        Slog.d(TAG, "begin getSubsystemLowPowerStats");
+        if (DBG) Slog.d(TAG, "begin getSubsystemLowPowerStats");
         try {
             mUtf8BufferStat.clear();
             mUtf16BufferStat.clear();
@@ -135,7 +150,7 @@
             mUtf16BufferStat.flip();
             return mUtf16BufferStat.toString();
         } finally {
-            Slog.d(TAG, "end getSubsystemLowPowerStats");
+            if (DBG) Slog.d(TAG, "end getSubsystemLowPowerStats");
         }
     }
 
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index cea80c8..8596113 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -19,6 +19,7 @@
 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
 import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
 import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
 import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
 import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
@@ -66,6 +67,7 @@
     private int mBeforeUnoccludeTransit;
     private int mVisibilityTransactionDepth;
     private SleepToken mSleepToken;
+    private int mSecondaryDisplayShowing = INVALID_DISPLAY;
 
     KeyguardController(ActivityManagerService service,
             ActivityStackSupervisor stackSupervisor) {
@@ -78,10 +80,12 @@
     }
 
     /**
-     * @return true if Keyguard is showing, not going away, and not being occluded, false otherwise
+     * @return true if Keyguard is showing, not going away, and not being occluded on the given
+     *         display, false otherwise
      */
-    boolean isKeyguardShowing() {
-        return mKeyguardShowing && !mKeyguardGoingAway && !mOccluded;
+    boolean isKeyguardShowing(int displayId) {
+        return mKeyguardShowing && !mKeyguardGoingAway &&
+                (displayId == DEFAULT_DISPLAY ? !mOccluded : displayId == mSecondaryDisplayShowing);
     }
 
     /**
@@ -94,15 +98,19 @@
     /**
      * Update the Keyguard showing state.
      */
-    void setKeyguardShown(boolean showing) {
-        if (showing == mKeyguardShowing) {
+    void setKeyguardShown(boolean showing, int secondaryDisplayShowing) {
+        boolean showingChanged = showing != mKeyguardShowing;
+        if (!showingChanged && secondaryDisplayShowing == mSecondaryDisplayShowing) {
             return;
         }
         mKeyguardShowing = showing;
-        dismissDockedStackIfNeeded();
-        if (showing) {
-            setKeyguardGoingAway(false);
-            mDismissalRequested = false;
+        mSecondaryDisplayShowing = secondaryDisplayShowing;
+        if (showingChanged) {
+            dismissDockedStackIfNeeded();
+            if (showing) {
+                setKeyguardGoingAway(false);
+                mDismissalRequested = false;
+            }
         }
         mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
         updateKeyguardSleepToken();
@@ -337,9 +345,9 @@
     }
 
     private void updateKeyguardSleepToken() {
-        if (mSleepToken == null && isKeyguardShowing()) {
+        if (mSleepToken == null && isKeyguardShowing(DEFAULT_DISPLAY)) {
             mSleepToken = mService.acquireSleepToken("Keyguard", DEFAULT_DISPLAY);
-        } else if (mSleepToken != null && !isKeyguardShowing()) {
+        } else if (mSleepToken != null && !isKeyguardShowing(DEFAULT_DISPLAY)) {
             mSleepToken.release();
             mSleepToken = null;
         }
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 1bbb068..eadc8a6 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -1112,19 +1112,6 @@
         return intent != null ? intent : affinityIntent;
     }
 
-    /**
-     * @return Whether there are only fullscreen activities in this task.
-     */
-    boolean containsOnlyFullscreenActivities() {
-        for (int i = 0; i < mActivities.size(); i++) {
-            final ActivityRecord r = mActivities.get(i);
-            if (!r.finishing && !r.fullscreen) {
-                return false;
-            }
-        }
-        return true;
-    }
-
     /** Returns the first non-finishing activity from the root. */
     ActivityRecord getRootActivity() {
         for (int i = 0; i < mActivities.size(); i++) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 91b1591..11d0470 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -6134,12 +6134,12 @@
     private int mSafeMediaVolumeIndex;
     // mSafeUsbMediaVolumeIndex is used for USB Headsets and is the music volume UI index
     // corresponding to a gain of -30 dBFS in audio flinger mixer.
-    // We remove -15 dBs from the theoretical -15dB to account for the EQ boost when bands are set
-    // to max gain.
+    // We remove -22 dBs from the theoretical -15dB to account for the EQ + bass boost
+    // amplification when both effects are on with all band gains at maximum.
     // This level corresponds to a loudness of 85 dB SPL for the warning to be displayed when
     // the headset is compliant to EN 60950 with a max loudness of 100dB SPL.
     private int mSafeUsbMediaVolumeIndex;
-    private static final float SAFE_VOLUME_GAIN_DBFS = -30.0f;
+    private static final float SAFE_VOLUME_GAIN_DBFS = -37.0f;
     // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
     private final int mSafeMediaVolumeDevices = AudioSystem.DEVICE_OUT_WIRED_HEADSET |
                                                 AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 27e4d14..d1a37af 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -171,7 +171,7 @@
             }
         }
         if (change) {
-            dispatchPlaybackChange();
+            dispatchPlaybackChange(false);
         }
     }
 
@@ -210,7 +210,7 @@
             }
         }
         if (change) {
-            dispatchPlaybackChange();
+            dispatchPlaybackChange(event == AudioPlaybackConfiguration.PLAYER_STATE_RELEASED);
         }
     }
 
@@ -244,6 +244,14 @@
         pw.println("\nPlaybackActivityMonitor dump time: "
                 + DateFormat.getTimeInstance().format(new Date()));
         synchronized(mPlayerLock) {
+            pw.println("\n  playback listeners:");
+            synchronized(mClients) {
+                for (PlayMonitorClient pmc : mClients) {
+                    pw.print(" " + (pmc.mIsPrivileged ? "(S)" : "(P)")
+                            + pmc.toString());
+                }
+            }
+            pw.println("\n");
             // all players
             pw.println("\n  players:");
             final List<Integer> piidIntList = new ArrayList<Integer>(mPlayers.keySet());
@@ -268,7 +276,7 @@
             for (int uid : mBannedUids) {
                 pw.print(" " + uid);
             }
-            pw.println();
+            pw.println("\n");
             // log
             mEventLogger.dump(pw);
         }
@@ -293,7 +301,11 @@
         return true;
     }
 
-    private void dispatchPlaybackChange() {
+    /**
+     * Sends new list after update of playback configurations
+     * @param iplayerReleased indicates if the change was due to a player being released
+     */
+    private void dispatchPlaybackChange(boolean iplayerReleased) {
         synchronized (mClients) {
             // typical use case, nobody is listening, don't do any work
             if (mClients.isEmpty()) {
@@ -324,9 +336,12 @@
                     // do not spam the logs if there are problems communicating with this client
                     if (pmc.mErrorCount < PlayMonitorClient.MAX_ERRORS) {
                         if (pmc.mIsPrivileged) {
-                            pmc.mDispatcherCb.dispatchPlaybackConfigChange(configsSystem);
+                            pmc.mDispatcherCb.dispatchPlaybackConfigChange(configsSystem,
+                                    iplayerReleased);
                         } else {
-                            pmc.mDispatcherCb.dispatchPlaybackConfigChange(configsPublic);
+                            // non-system clients don't have the control interface IPlayer, so
+                            // they don't need to flush commands when a player was released
+                            pmc.mDispatcherCb.dispatchPlaybackConfigChange(configsPublic, false);
                         }
                     }
                 } catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/broadcastradio/Tuner.java b/services/core/java/com/android/server/broadcastradio/Tuner.java
index 06a5af5..e6ae320 100644
--- a/services/core/java/com/android/server/broadcastradio/Tuner.java
+++ b/services/core/java/com/android/server/broadcastradio/Tuner.java
@@ -77,6 +77,8 @@
             @NonNull RadioManager.BandConfig config);
     private native RadioManager.BandConfig nativeGetConfiguration(long nativeContext, int region);
 
+    private native void nativeSetMuted(long nativeContext, boolean mute);
+
     private native void nativeStep(long nativeContext, boolean directionDown, boolean skipSubChannel);
     private native void nativeScan(long nativeContext, boolean directionDown, boolean skipSubChannel);
     private native void nativeTune(long nativeContext, @NonNull ProgramSelector selector);
@@ -148,8 +150,7 @@
             if (mIsMuted == mute) return;
             mIsMuted = mute;
 
-            // TODO(b/62713378): notifify audio policy manager of media activity on radio audio
-            // device. This task is pulled directly from previous implementation of native service.
+            nativeSetMuted(mNativeContext, mute);
         }
     }
 
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index db72c5e..e6228d4 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -20,6 +20,7 @@
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
 import android.app.IActivityManager;
+import android.app.KeyguardManager;
 import android.content.ClipData;
 import android.content.ClipDescription;
 import android.content.ContentProvider;
@@ -304,7 +305,7 @@
         public ClipData getPrimaryClip(String pkg) {
             synchronized (this) {
                 if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, pkg,
-                            Binder.getCallingUid())) {
+                            Binder.getCallingUid()) || isDeviceLocked()) {
                     return null;
                 }
                 addActiveOwnerLocked(Binder.getCallingUid(), pkg);
@@ -316,7 +317,7 @@
         public ClipDescription getPrimaryClipDescription(String callingPackage) {
             synchronized (this) {
                 if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage,
-                            Binder.getCallingUid())) {
+                            Binder.getCallingUid()) || isDeviceLocked()) {
                     return null;
                 }
                 PerUserClipboard clipboard = getClipboard();
@@ -328,7 +329,7 @@
         public boolean hasPrimaryClip(String callingPackage) {
             synchronized (this) {
                 if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage,
-                            Binder.getCallingUid())) {
+                            Binder.getCallingUid()) || isDeviceLocked()) {
                     return false;
                 }
                 return getClipboard().primaryClip != null;
@@ -355,7 +356,7 @@
         public boolean hasClipboardText(String callingPackage) {
             synchronized (this) {
                 if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage,
-                            Binder.getCallingUid())) {
+                            Binder.getCallingUid()) || isDeviceLocked()) {
                     return false;
                 }
                 PerUserClipboard clipboard = getClipboard();
@@ -433,6 +434,17 @@
         }
     }
 
+    private boolean isDeviceLocked() {
+        final long token = Binder.clearCallingIdentity();
+        try {
+            final KeyguardManager keyguardManager = getContext().getSystemService(
+                    KeyguardManager.class);
+            return keyguardManager != null && keyguardManager.isDeviceLocked();
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
     private final void checkUriOwnerLocked(Uri uri, int uid) {
         if (!"content".equals(uri.getScheme())) {
             return;
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
index 788867f..5eafe5f 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
@@ -30,6 +30,10 @@
 import android.net.LinkProperties;
 import android.net.NetworkStats;
 import android.net.RouteInfo;
+import android.net.netlink.ConntrackMessage;
+import android.net.netlink.NetlinkConstants;
+import android.net.netlink.NetlinkSocket;
+import android.net.util.IpUtils;
 import android.net.util.SharedLog;
 import android.os.Handler;
 import android.os.Looper;
@@ -37,10 +41,12 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.provider.Settings;
+import android.system.ErrnoException;
+import android.system.OsConstants;
 import android.text.TextUtils;
-import com.android.server.connectivity.tethering.OffloadHardwareInterface.ForwardedStats;
 
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.connectivity.tethering.OffloadHardwareInterface.ForwardedStats;
 
 import java.net.Inet4Address;
 import java.net.Inet6Address;
@@ -63,6 +69,7 @@
  */
 public class OffloadController {
     private static final String TAG = OffloadController.class.getSimpleName();
+    private static final boolean DBG = false;
     private static final String ANYIP = "0.0.0.0";
     private static final ForwardedStats EMPTY_STATS = new ForwardedStats();
 
@@ -96,6 +103,9 @@
     // includes upstream interfaces that have a quota set.
     private HashMap<String, Long> mInterfaceQuotas = new HashMap<>();
 
+    private int mNatUpdateCallbacksReceived;
+    private int mNatUpdateNetlinkErrors;
+
     public OffloadController(Handler h, OffloadHardwareInterface hwi,
             ContentResolver contentResolver, INetworkManagementService nms, SharedLog log) {
         mHandler = h;
@@ -115,12 +125,12 @@
         }
     }
 
-    public void start() {
-        if (started()) return;
+    public boolean start() {
+        if (started()) return true;
 
         if (isOffloadDisabled()) {
             mLog.i("tethering offload disabled");
-            return;
+            return false;
         }
 
         if (!mConfigInitialized) {
@@ -128,11 +138,14 @@
             if (!mConfigInitialized) {
                 mLog.i("tethering offload config not supported");
                 stop();
-                return;
+                return false;
             }
         }
 
         mControlInitialized = mHwInterface.initOffloadControl(
+                // OffloadHardwareInterface guarantees that these callback
+                // methods are called on the handler passed to it, which is the
+                // same as mHandler, as coordinated by the setup in Tethering.
                 new OffloadHardwareInterface.ControlCallback() {
                     @Override
                     public void onStarted() {
@@ -203,15 +216,20 @@
                                                    String srcAddr, int srcPort,
                                                    String dstAddr, int dstPort) {
                         if (!started()) return;
-                        mLog.log(String.format("NAT timeout update: %s (%s,%s) -> (%s,%s)",
-                                proto, srcAddr, srcPort, dstAddr, dstPort));
+                        updateNatTimeout(proto, srcAddr, srcPort, dstAddr, dstPort);
                     }
                 });
-        if (!mControlInitialized) {
+
+        final boolean isStarted = started();
+        if (!isStarted) {
             mLog.i("tethering offload control not supported");
             stop();
+        } else {
+            mLog.log("tethering offload started");
+            mNatUpdateCallbacksReceived = 0;
+            mNatUpdateNetlinkErrors = 0;
         }
-        mLog.log("tethering offload started");
+        return isStarted;
     }
 
     public void stop() {
@@ -227,6 +245,10 @@
         if (wasStarted) mLog.log("tethering offload stopped");
     }
 
+    private boolean started() {
+        return mConfigInitialized && mControlInitialized;
+    }
+
     private class OffloadTetheringStatsProvider extends ITetheringStatsProvider.Stub {
         @Override
         public NetworkStats getTetherStats(int how) {
@@ -402,10 +424,6 @@
                 mContentResolver, TETHER_OFFLOAD_DISABLED, defaultDisposition) != 0);
     }
 
-    private boolean started() {
-        return mConfigInitialized && mControlInitialized;
-    }
-
     private boolean pushUpstreamParameters(String prevUpstream) {
         final String iface = currentUpstreamInterface();
 
@@ -516,10 +534,113 @@
             pw.println("Offload disabled");
             return;
         }
-        pw.println("Offload HALs " + (started() ? "started" : "not started"));
+        final boolean isStarted = started();
+        pw.println("Offload HALs " + (isStarted ? "started" : "not started"));
         LinkProperties lp = mUpstreamLinkProperties;
         String upstream = (lp != null) ? lp.getInterfaceName() : null;
         pw.println("Current upstream: " + upstream);
         pw.println("Exempt prefixes: " + mLastLocalPrefixStrs);
+        pw.println("NAT timeout update callbacks received during the "
+                + (isStarted ? "current" : "last")
+                + " offload session: "
+                + mNatUpdateCallbacksReceived);
+        pw.println("NAT timeout update netlink errors during the "
+                + (isStarted ? "current" : "last")
+                + " offload session: "
+                + mNatUpdateNetlinkErrors);
+    }
+
+    private void updateNatTimeout(
+            int proto, String srcAddr, int srcPort, String dstAddr, int dstPort) {
+        final String protoName = protoNameFor(proto);
+        if (protoName == null) {
+            mLog.e("Unknown NAT update callback protocol: " + proto);
+            return;
+        }
+
+        final Inet4Address src = parseIPv4Address(srcAddr);
+        if (src == null) {
+            mLog.e("Failed to parse IPv4 address: " + srcAddr);
+            return;
+        }
+
+        if (!IpUtils.isValidUdpOrTcpPort(srcPort)) {
+            mLog.e("Invalid src port: " + srcPort);
+            return;
+        }
+
+        final Inet4Address dst = parseIPv4Address(dstAddr);
+        if (dst == null) {
+            mLog.e("Failed to parse IPv4 address: " + dstAddr);
+            return;
+        }
+
+        if (!IpUtils.isValidUdpOrTcpPort(dstPort)) {
+            mLog.e("Invalid dst port: " + dstPort);
+            return;
+        }
+
+        mNatUpdateCallbacksReceived++;
+        if (DBG) {
+            mLog.log(String.format("NAT timeout update: %s (%s, %s) -> (%s, %s)",
+                     protoName, srcAddr, srcPort, dstAddr, dstPort));
+        }
+
+        final int timeoutSec = connectionTimeoutUpdateSecondsFor(proto);
+        final byte[] msg = ConntrackMessage.newIPv4TimeoutUpdateRequest(
+                proto, src, srcPort, dst, dstPort, timeoutSec);
+
+        try {
+            NetlinkSocket.sendOneShotKernelMessage(OsConstants.NETLINK_NETFILTER, msg);
+        } catch (ErrnoException e) {
+            mNatUpdateNetlinkErrors++;
+            mLog.e("Error updating NAT conntrack entry: " + e
+                    + ", msg: " + NetlinkConstants.hexify(msg));
+            mLog.log("NAT timeout update callbacks received: " + mNatUpdateCallbacksReceived);
+            mLog.log("NAT timeout update netlink errors: " + mNatUpdateNetlinkErrors);
+        }
+    }
+
+    private static Inet4Address parseIPv4Address(String addrString) {
+        try {
+            final InetAddress ip = InetAddress.parseNumericAddress(addrString);
+            // TODO: Consider other sanitization steps here, including perhaps:
+            //           not eql to 0.0.0.0
+            //           not within 169.254.0.0/16
+            //           not within ::ffff:0.0.0.0/96
+            //           not within ::/96
+            // et cetera.
+            if (ip instanceof Inet4Address) {
+                return (Inet4Address) ip;
+            }
+        } catch (IllegalArgumentException iae) {}
+        return null;
+    }
+
+    private static String protoNameFor(int proto) {
+        // OsConstants values are not constant expressions; no switch statement.
+        if (proto == OsConstants.IPPROTO_UDP) {
+            return "UDP";
+        } else if (proto == OsConstants.IPPROTO_TCP) {
+            return "TCP";
+        }
+        return null;
+    }
+
+    private static int connectionTimeoutUpdateSecondsFor(int proto) {
+        // TODO: Replace this with more thoughtful work, perhaps reading from
+        // and maybe writing to any required
+        //
+        //     /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_*
+        //     /proc/sys/net/netfilter/nf_conntrack_udp_timeout{,_stream}
+        //
+        // entries.  TBD.
+        if (proto == OsConstants.IPPROTO_TCP) {
+            // Cf. /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established
+            return 432000;
+        } else {
+            // Cf. /proc/sys/net/netfilter/nf_conntrack_udp_timeout_stream
+            return 180;
+        }
     }
 }
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
index 865a989..76195c4 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
@@ -21,10 +21,12 @@
 import android.hardware.tetheroffload.control.V1_0.IOffloadControl;
 import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback;
 import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate;
+import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
 import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.net.util.SharedLog;
+import android.system.OsConstants;
 
 import java.util.ArrayList;
 
@@ -107,6 +109,10 @@
                 mLog.e("tethering offload control not supported: " + e);
                 return false;
             }
+            if (mOffloadControl == null) {
+                mLog.e("tethering IOffloadControl.getService() returned null");
+                return false;
+            }
         }
 
         final String logmsg = String.format("initOffloadControl(%s)",
@@ -327,13 +333,24 @@
         public void updateTimeout(NatTimeoutUpdate params) {
             handler.post(() -> {
                     controlCb.onNatTimeoutUpdate(
-                        params.proto,
+                        networkProtocolToOsConstant(params.proto),
                         params.src.addr, uint16(params.src.port),
                         params.dst.addr, uint16(params.dst.port));
             });
         }
     }
 
+    private static int networkProtocolToOsConstant(int proto) {
+        switch (proto) {
+            case NetworkProtocol.TCP: return OsConstants.IPPROTO_TCP;
+            case NetworkProtocol.UDP: return OsConstants.IPPROTO_UDP;
+            default:
+                // The caller checks this value and will log an error. Just make
+                // sure it won't collide with valid OsContants.IPPROTO_* values.
+                return -Math.abs(proto);
+        }
+    }
+
     private static class CbResults {
         boolean success;
         String errMsg;
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 018b5fa4..11043bd 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -1142,12 +1142,13 @@
                 continue;
             }
             try {
-                result.put(userId, getDecryptedPasswordForTiedProfile(userId));
+                result.put(managedUserId, getDecryptedPasswordForTiedProfile(managedUserId));
             } catch (KeyStoreException | UnrecoverableKeyException | NoSuchAlgorithmException
                     | NoSuchPaddingException | InvalidKeyException
                     | InvalidAlgorithmParameterException | IllegalBlockSizeException
                     | BadPaddingException | CertificateException | IOException e) {
-                // ignore
+                Slog.e(TAG, "getDecryptedPasswordsForAllTiedProfiles failed for user " +
+                    managedUserId, e);
             }
         }
         return result;
diff --git a/services/core/java/com/android/server/media/AudioPlaybackMonitor.java b/services/core/java/com/android/server/media/AudioPlaybackMonitor.java
index f6f7676..791ee82 100644
--- a/services/core/java/com/android/server/media/AudioPlaybackMonitor.java
+++ b/services/core/java/com/android/server/media/AudioPlaybackMonitor.java
@@ -100,7 +100,11 @@
      * @param configs List of the current audio playback configuration
      */
     @Override
-    public void dispatchPlaybackConfigChange(List<AudioPlaybackConfiguration> configs) {
+    public void dispatchPlaybackConfigChange(List<AudioPlaybackConfiguration> configs,
+            boolean flush) {
+        if (flush) {
+            Binder.flushPendingCommands();
+        }
         final long token = Binder.clearCallingIdentity();
         try {
             List<Integer> newActiveAudioPlaybackClientUids = new ArrayList<>();
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 07ab417..9fd54ec 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -113,16 +113,20 @@
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
 import android.net.IConnectivityManager;
 import android.net.INetworkManagementEventObserver;
 import android.net.INetworkPolicyListener;
 import android.net.INetworkPolicyManager;
 import android.net.INetworkStatsService;
 import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkCapabilities;
 import android.net.NetworkIdentity;
 import android.net.NetworkPolicy;
 import android.net.NetworkPolicyManager;
 import android.net.NetworkQuotaInfo;
+import android.net.NetworkRequest;
 import android.net.NetworkState;
 import android.net.NetworkTemplate;
 import android.net.TrafficStats;
@@ -444,6 +448,10 @@
     @GuardedBy("mUidRulesFirstLock")
     final SparseIntArray mUidState = new SparseIntArray();
 
+    /** Map from network ID to last observed meteredness state */
+    @GuardedBy("mNetworkPoliciesSecondLock")
+    private final SparseBooleanArray mNetworkMetered = new SparseBooleanArray();
+
     private final RemoteCallbackList<INetworkPolicyListener>
             mListeners = new RemoteCallbackList<>();
 
@@ -782,6 +790,10 @@
                     ACTION_CARRIER_CONFIG_CHANGED);
             mContext.registerReceiver(mCarrierConfigReceiver, carrierConfigFilter, null, mHandler);
 
+            // listen for meteredness changes
+            mContext.getSystemService(ConnectivityManager.class).registerNetworkCallback(
+                    new NetworkRequest.Builder().build(), mNetworkCallback);
+
             mUsageStats.addAppIdleStateChangeListener(new AppIdleStateChangeListener());
             // tell systemReady() that the service has been initialized
             initCompleteSignal.countDown();
@@ -981,6 +993,26 @@
             synchronized (mUidRulesFirstLock) {
                 synchronized (mNetworkPoliciesSecondLock) {
                     upgradeWifiMeteredOverrideAL();
+                }
+            }
+            // Only need to perform upgrade logic once
+            mContext.unregisterReceiver(this);
+        }
+    };
+
+    private final NetworkCallback mNetworkCallback = new NetworkCallback() {
+        @Override
+        public void onCapabilitiesChanged(Network network,
+                NetworkCapabilities networkCapabilities) {
+            if (network == null || networkCapabilities == null) return;
+
+            synchronized (mNetworkPoliciesSecondLock) {
+                final boolean oldMetered = mNetworkMetered.get(network.netId, false);
+                final boolean newMetered = !networkCapabilities
+                        .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+
+                if ((oldMetered != newMetered) || mNetworkMetered.indexOfKey(network.netId) < 0) {
+                    mNetworkMetered.put(network.netId, newMetered);
                     updateNetworkRulesNL();
                 }
             }
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 34f1bfa..add4184 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -99,6 +99,7 @@
     protected final Object mMutex;
     private final UserProfiles mUserProfiles;
     private final IPackageManager mPm;
+    private final UserManager mUm;
     private final Config mConfig;
 
     // contains connections to all connected services, including app services
@@ -138,6 +139,7 @@
         mPm = pm;
         mConfig = getConfig();
         mApprovalLevel = APPROVAL_BY_COMPONENT;
+        mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
     }
 
     abstract protected Config getConfig();
@@ -296,7 +298,9 @@
                     final int userId = XmlUtils.readIntAttribute(parser, ATT_USER_ID, 0);
                     final boolean isPrimary =
                             XmlUtils.readBooleanAttribute(parser, ATT_IS_PRIMARY, true);
-                    addApprovedList(approved, userId, isPrimary);
+                    if (mUm.getUserInfo(userId) != null) {
+                        addApprovedList(approved, userId, isPrimary);
+                    }
                     mUseXml = true;
                 }
             }
@@ -494,7 +498,7 @@
             return info;
         }
         throw new SecurityException("Disallowed call from unknown " + getCaption() + ": "
-                + service);
+                + service + " " + service.getClass());
     }
 
     public void unregisterService(IInterface service, int userid) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 44e571a..92b360b 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -756,9 +756,12 @@
                 if (r != null) {
                     r.stats.onExpansionChanged(userAction, expanded);
                     final long now = System.currentTimeMillis();
-                    MetricsLogger.action(r.getLogMaker(now)
-                            .setCategory(MetricsEvent.NOTIFICATION_ITEM)
-                            .setType(MetricsEvent.TYPE_DETAIL));
+                    if (userAction) {
+                        MetricsLogger.action(r.getLogMaker(now)
+                                .setCategory(MetricsEvent.NOTIFICATION_ITEM)
+                                .setType(expanded ? MetricsEvent.TYPE_DETAIL
+                                        : MetricsEvent.TYPE_COLLAPSE));
+                    }
                     EventLogTags.writeNotificationExpansion(key,
                             userAction ? 1 : 0, expanded ? 1 : 0,
                             r.getLifespanMs(now), r.getFreshnessMs(now), r.getExposureMs(now));
@@ -1461,8 +1464,18 @@
         if (channel.getImportance() == NotificationManager.IMPORTANCE_NONE) {
             // cancel
             cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channel.getId(), 0, 0, true,
-                    UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED,
+                    UserHandle.getUserId(uid), REASON_CHANNEL_BANNED,
                     null);
+            if (isUidSystemOrPhone(uid)) {
+                int[] profileIds = mUserProfiles.getCurrentProfileIds();
+                int N = profileIds.length;
+                for (int i = 0; i < N; i++) {
+                    int profileId = profileIds[i];
+                    cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channel.getId(), 0, 0, true,
+                            profileId, REASON_CHANNEL_BANNED,
+                            null);
+                }
+            }
         }
         mRankingHelper.updateNotificationChannel(pkg, uid, channel);
 
@@ -2737,17 +2750,22 @@
         public void setNotificationPolicyAccessGranted(String pkg, boolean granted)
                 throws RemoteException {
             checkCallerIsSystemOrShell();
-            if (!mActivityManager.isLowRamDevice()) {
-                mConditionProviders.setPackageOrComponentEnabled(
-                        pkg, getCallingUserHandle().getIdentifier(), true, granted);
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                if (!mActivityManager.isLowRamDevice()) {
+                    mConditionProviders.setPackageOrComponentEnabled(
+                            pkg, getCallingUserHandle().getIdentifier(), true, granted);
 
-                getContext().sendBroadcastAsUser(new Intent(
-                        NotificationManager.ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED)
-                                .setPackage(pkg)
-                                .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
-                        getCallingUserHandle(), null);
+                    getContext().sendBroadcastAsUser(new Intent(
+                            NotificationManager.ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED)
+                                    .setPackage(pkg)
+                                    .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
+                            getCallingUserHandle(), null);
 
-                savePolicyFile();
+                    savePolicyFile();
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
             }
         }
 
@@ -2829,19 +2847,25 @@
                 boolean granted) throws RemoteException {
             Preconditions.checkNotNull(listener);
             checkCallerIsSystemOrShell();
-            if (!mActivityManager.isLowRamDevice()) {
-                mConditionProviders.setPackageOrComponentEnabled(listener.flattenToString(),
-                        userId, false, granted);
-                mListeners.setPackageOrComponentEnabled(listener.flattenToString(),
-                        userId, true, granted);
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                if (!mActivityManager.isLowRamDevice()) {
+                    mConditionProviders.setPackageOrComponentEnabled(listener.flattenToString(),
+                            userId, false, granted);
+                    mListeners.setPackageOrComponentEnabled(listener.flattenToString(),
+                            userId, true, granted);
 
-                getContext().sendBroadcastAsUser(new Intent(
-                        NotificationManager.ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED)
-                                .setPackage(listener.getPackageName())
-                                .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
-                        getCallingUserHandle(), null);
+                    getContext().sendBroadcastAsUser(new Intent(
+                                    NotificationManager.ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED)
 
-                savePolicyFile();
+                                    .setPackage(listener.getPackageName())
+                                    .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
+                            getCallingUserHandle(), null);
+
+                    savePolicyFile();
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
             }
         }
 
@@ -2850,19 +2874,24 @@
                 int userId, boolean granted) throws RemoteException {
             Preconditions.checkNotNull(assistant);
             checkCallerIsSystemOrShell();
-            if (!mActivityManager.isLowRamDevice()) {
-                mConditionProviders.setPackageOrComponentEnabled(assistant.flattenToString(),
-                        userId, false, granted);
-                mAssistants.setPackageOrComponentEnabled(assistant.flattenToString(),
-                        userId, true, granted);
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                if (!mActivityManager.isLowRamDevice()) {
+                    mConditionProviders.setPackageOrComponentEnabled(assistant.flattenToString(),
+                            userId, false, granted);
+                    mAssistants.setPackageOrComponentEnabled(assistant.flattenToString(),
+                            userId, true, granted);
 
-                getContext().sendBroadcastAsUser(new Intent(
-                        NotificationManager.ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED)
-                                .setPackage(assistant.getPackageName())
-                                .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
-                        getCallingUserHandle(), null);
+                    getContext().sendBroadcastAsUser(new Intent(
+                            NotificationManager.ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED)
+                                    .setPackage(assistant.getPackageName())
+                                    .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
+                            getCallingUserHandle(), null);
 
-                savePolicyFile();
+                    savePolicyFile();
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
             }
         }
 
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 3386fe83..f193a19 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -1174,7 +1174,7 @@
             changed |= oldValue != newValue;
         }
         if (changed) {
-            mRankingHandler.requestSort();
+            updateConfig();
         }
     }
 
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 1a0b878..ffdafc5 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -465,6 +465,8 @@
                             + "from " + currRule.getName() + " to " + defaultRule.name);
                     // update default rule (if locale changed, name of rule will change)
                     AutomaticZenRule defaultAutoRule = createAutomaticZenRule(defaultRule);
+                    // ensure enabled state is carried over from current rule
+                    defaultAutoRule.setEnabled(currRule.isEnabled());
                     updateAutomaticZenRule(ruleId, defaultAutoRule,
                             "locale changed");
                 }
@@ -735,6 +737,9 @@
             mConfig = config;
             mHandler.postApplyConfig(config, reason, setRingerMode);
             return true;
+        } catch (SecurityException e) {
+            Log.wtf(TAG, "Invalid rule in config", e);
+            return false;
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/services/core/java/com/android/server/oemlock/OemLockService.java b/services/core/java/com/android/server/oemlock/OemLockService.java
index 5e19b13..40c6639 100644
--- a/services/core/java/com/android/server/oemlock/OemLockService.java
+++ b/services/core/java/com/android/server/oemlock/OemLockService.java
@@ -149,8 +149,12 @@
 
             final long token = Binder.clearCallingIdentity();
             try {
-                if (!canUserAllowOemUnlock()) {
-                    throw new SecurityException("User cannot allow OEM unlock");
+                if (!isOemUnlockAllowedByAdmin()) {
+                    throw new SecurityException("Admin does not allow OEM unlock");
+                }
+
+                if (!mOemLock.isOemUnlockAllowedByCarrier()) {
+                    throw new SecurityException("Carrier does not allow OEM unlock");
                 }
 
                 mOemLock.setOemUnlockAllowedByDevice(allowedByUser);
@@ -172,18 +176,6 @@
         }
 
         @Override
-        public boolean canUserAllowOemUnlock() {
-            enforceOemUnlockReadPermission();
-
-            final long token = Binder.clearCallingIdentity();
-            try {
-                return isOemUnlockAllowedByAdmin() && mOemLock.isOemUnlockAllowedByCarrier();
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-        @Override
         public boolean isOemUnlockAllowed() {
             enforceOemUnlockReadPermission();
 
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index 1082eae..a3811ba 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -18,6 +18,7 @@
 
 import android.Manifest;
 import android.annotation.NonNull;
+import android.app.ActivityManager;
 import android.app.DownloadManager;
 import android.app.admin.DevicePolicyManager;
 import android.companion.CompanionDeviceManager;
@@ -582,6 +583,21 @@
                 }
             }
 
+            if (ActivityManager.isLowRamDeviceStatic()) {
+                // Allow voice search on low-ram devices
+                Intent globalSearchIntent = new Intent("android.search.action.GLOBAL_SEARCH");
+                PackageParser.Package globalSearchPickerPackage =
+                    getDefaultSystemHandlerActivityPackageLPr(globalSearchIntent, userId);
+
+                if (globalSearchPickerPackage != null
+                        && doesPackageSupportRuntimePermissions(globalSearchPickerPackage)) {
+                    grantRuntimePermissionsLPw(globalSearchPickerPackage,
+                        MICROPHONE_PERMISSIONS, true, userId);
+                    grantRuntimePermissionsLPw(globalSearchPickerPackage,
+                        LOCATION_PERMISSIONS, true, userId);
+                }
+            }
+
             // Voice recognition
             Intent voiceRecoIntent = new Intent("android.speech.RecognitionService");
             voiceRecoIntent.addCategory(Intent.CATEGORY_DEFAULT);
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index da6e26e..6253857 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -53,7 +53,8 @@
     private final static boolean DEBUG_DEXOPT = true;
 
     // The synthetic library dependencies denoting "no checks."
-    private final static String[] NO_LIBRARIES = new String[] { "&" };
+    private final static String[] NO_LIBRARIES =
+            new String[] { PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK };
 
     // The amount of "available" (free - low threshold) space necessary at the start of an OTA to
     // not bulk-delete unused apps' odex files.
@@ -322,11 +323,6 @@
                 new DexoptOptions(pkg.packageName, compilationReason,
                         DexoptOptions.DEXOPT_BOOT_COMPLETE));
 
-        mPackageManagerService.getDexManager().dexoptSecondaryDex(
-                new DexoptOptions(pkg.packageName, compilationReason,
-                        DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX |
-                        DexoptOptions.DEXOPT_BOOT_COMPLETE));
-
         return commands;
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 698d387..4fafe34 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -147,8 +147,13 @@
         // Get the class loader context dependencies.
         // For each code path in the package, this array contains the class loader context that
         // needs to be passed to dexopt in order to ensure correct optimizations.
+        boolean[] pathsWithCode = new boolean[paths.size()];
+        pathsWithCode[0] = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0;
+        for (int i = 1; i < paths.size(); i++) {
+            pathsWithCode[i] = (pkg.splitFlags[i - 1] & ApplicationInfo.FLAG_HAS_CODE) != 0;
+        }
         String[] classLoaderContexts = DexoptUtils.getClassLoaderContexts(
-                pkg.applicationInfo, sharedLibraries);
+                pkg.applicationInfo, sharedLibraries, pathsWithCode);
 
         // Sanity check that we do not call dexopt with inconsistent data.
         if (paths.size() != classLoaderContexts.length) {
@@ -164,10 +169,15 @@
         int result = DEX_OPT_SKIPPED;
         for (int i = 0; i < paths.size(); i++) {
             // Skip paths that have no code.
-            if ((i == 0 && (pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) == 0) ||
-                    (i != 0 && (pkg.splitFlags[i - 1] & ApplicationInfo.FLAG_HAS_CODE) == 0)) {
+            if (!pathsWithCode[i]) {
                 continue;
             }
+            if (classLoaderContexts[i] == null) {
+                throw new IllegalStateException("Inconsistent information in the "
+                        + "package structure. A split is marked to contain code "
+                        + "but has no dependency listed. Index=" + i + " path=" + paths.get(i));
+            }
+
             // Append shared libraries with split dependencies for this split.
             String path = paths.get(i);
             if (options.getSplitName() != null) {
@@ -428,16 +438,7 @@
                     PackageDexUsage.DexUseInfo dexUseInfo = e.getValue();
                     pw.println(dex);
                     pw.increaseIndent();
-                    for (String isa : dexUseInfo.getLoaderIsas()) {
-                        String status = null;
-                        try {
-                            status = DexFile.getDexFileStatus(path, isa);
-                        } catch (IOException ioe) {
-                             status = "[Exception]: " + ioe.getMessage();
-                        }
-                        pw.println(isa + ": " + status);
-                    }
-
+                    // TODO(calin): get the status of the oat file (needs installd call)
                     pw.println("class loader context: " + dexUseInfo.getClassLoaderContext());
                     if (dexUseInfo.isUsedByOtherApps()) {
                         pw.println("used be other apps: " + dexUseInfo.getLoadingPackages());
@@ -464,8 +465,9 @@
         }
 
         if (isProfileGuidedCompilerFilter(targetCompilerFilter) && isUsedByOtherApps) {
-            // If the dex files is used by other apps, we cannot use profile-guided compilation.
-            return getNonProfileGuidedCompilerFilter(targetCompilerFilter);
+            // If the dex files is used by other apps, apply the shared filter.
+            return PackageManagerServiceCompilerMapping.getCompilerFilterForReason(
+                    PackageManagerService.REASON_SHARED);
         }
 
         return targetCompilerFilter;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index c3b93b4..1fa37b9 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -319,9 +319,15 @@
                 if (type == START_TAG) {
                     final String tag = in.getName();
                     if (PackageInstallerSession.TAG_SESSION.equals(tag)) {
-                        final PackageInstallerSession session = PackageInstallerSession.
-                                readFromXml(in, mInternalCallback, mContext, mPm,
-                                        mInstallThread.getLooper(), mSessionsDir);
+                        final PackageInstallerSession session;
+                        try {
+                            session = PackageInstallerSession.readFromXml(in, mInternalCallback,
+                                    mContext, mPm, mInstallThread.getLooper(), mSessionsDir);
+                        } catch (Exception e) {
+                            Slog.e(TAG, "Could not read session", e);
+                            continue;
+                        }
+
                         final long age = System.currentTimeMillis() - session.createdMillis;
 
                         final boolean valid;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index fddbd67..3f1c8a1 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -118,6 +118,7 @@
     private static final String REMOVE_SPLIT_MARKER_EXTENSION = ".removed";
 
     private static final int MSG_COMMIT = 0;
+    private static final int MSG_SESSION_FINISHED_WITH_EXCEPTION = 1;
 
     /** XML constants used for persisting a session */
     static final String TAG_SESSION = "session";
@@ -274,15 +275,27 @@
     private final Handler.Callback mHandlerCallback = new Handler.Callback() {
         @Override
         public boolean handleMessage(Message msg) {
-            synchronized (mLock) {
-                try {
-                    commitLocked();
-                } catch (PackageManagerException e) {
-                    final String completeMsg = ExceptionUtils.getCompleteMessage(e);
-                    Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
-                    destroyInternal();
-                    dispatchSessionFinished(e.error, completeMsg, null);
-                }
+            switch (msg.what) {
+                case MSG_COMMIT:
+                    synchronized (mLock) {
+                        try {
+                            commitLocked();
+                        } catch (PackageManagerException e) {
+                            final String completeMsg = ExceptionUtils.getCompleteMessage(e);
+                            Slog.e(TAG,
+                                    "Commit of session " + sessionId + " failed: " + completeMsg);
+                            destroyInternal();
+                            dispatchSessionFinished(e.error, completeMsg, null);
+                        }
+                    }
+
+                    break;
+                case MSG_SESSION_FINISHED_WITH_EXCEPTION:
+                    PackageManagerException e = (PackageManagerException) msg.obj;
+
+                    dispatchSessionFinished(e.error, ExceptionUtils.getCompleteMessage(e),
+                            null);
+                    break;
             }
 
             return true;
@@ -351,7 +364,17 @@
         }
 
         mPrepared = prepared;
-        mSealed = sealed;
+
+        if (sealed) {
+            synchronized (mLock) {
+                try {
+                    sealAndValidateLocked();
+                } catch (PackageManagerException | IOException e) {
+                    destroyInternal();
+                    throw new IllegalArgumentException(e);
+                }
+            }
+        }
 
         final long identity = Binder.clearCallingIdentity();
         try {
@@ -667,11 +690,6 @@
     public void commit(@NonNull IntentSender statusReceiver, boolean forTransfer) {
         Preconditions.checkNotNull(statusReceiver);
 
-        // Cache package manager data without the lock held
-        final PackageInfo installedPkgInfo = mPm.getPackageInfo(
-                params.appPackageName, PackageManager.GET_SIGNATURES
-                        | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
-
         final boolean wasSealed;
         synchronized (mLock) {
             assertCallerIsOwnerOrRootLocked();
@@ -696,11 +714,17 @@
             wasSealed = mSealed;
             if (!mSealed) {
                 try {
-                    sealAndValidateLocked(installedPkgInfo);
+                    sealAndValidateLocked();
+                } catch (IOException e) {
+                    throw new IllegalArgumentException(e);
                 } catch (PackageManagerException e) {
-                    // Do now throw an exception here to stay compatible with O and older
                     destroyInternal();
-                    dispatchSessionFinished(e.error, ExceptionUtils.getCompleteMessage(e), null);
+
+                    // Cannot call dispatchFinal synchronous as this might be called from inside the
+                    // system server on the main thread. Hence the call back scheduled in
+                    // dispachFinal has to be scheduled on a different thread.
+                    mHandler.obtainMessage(MSG_SESSION_FINISHED_WITH_EXCEPTION, e).sendToTarget();
+
                     return;
                 }
             }
@@ -730,18 +754,33 @@
      *
      * <p>The session will be sealed after calling this method even if it failed.
      *
-     * @param pkgInfo The package info for {@link #params}.packagename
+     * @throws PackageManagerException if the session was sealed but something went wrong. If the
+     *                                 session was sealed this is the only possible exception.
      */
-    private void sealAndValidateLocked(@Nullable PackageInfo pkgInfo)
-            throws PackageManagerException {
+    private void sealAndValidateLocked() throws PackageManagerException, IOException {
         assertNoWriteFileTransfersOpenLocked();
+        assertPreparedAndNotDestroyedLocked("sealing of session");
+
+        final PackageInfo pkgInfo = mPm.getPackageInfo(
+                params.appPackageName, PackageManager.GET_SIGNATURES
+                        | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
+
+        resolveStageDirLocked();
 
         mSealed = true;
 
         // Verify that stage looks sane with respect to existing application.
         // This currently only ensures packageName, versionCode, and certificate
         // consistency.
-        validateInstallLocked(pkgInfo);
+        try {
+            validateInstallLocked(pkgInfo);
+        } catch (PackageManagerException e) {
+            throw e;
+        } catch (Throwable e) {
+            // Convert all exceptions into package manager exceptions as only those are handled
+            // in the code above
+            throw new PackageManagerException(e);
+        }
 
         // Read transfers from the original owner stay open, but as the session's data
         // cannot be modified anymore, there is no leak of information.
@@ -762,11 +801,6 @@
                     + "the " + Manifest.permission.INSTALL_PACKAGES + " permission");
         }
 
-        // Cache package manager data without the lock held
-        final PackageInfo installedPkgInfo = mPm.getPackageInfo(
-                params.appPackageName, PackageManager.GET_SIGNATURES
-                        | PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
-
         // Only install flags that can be verified by the app the session is transferred to are
         // allowed. The parameters can be read via PackageInstaller.SessionInfo.
         if (!params.areHiddenOptionsSet()) {
@@ -778,8 +812,14 @@
             assertPreparedAndNotSealedLocked("transfer");
 
             try {
-                sealAndValidateLocked(installedPkgInfo);
+                sealAndValidateLocked();
+            } catch (IOException e) {
+                throw new IllegalStateException(e);
             } catch (PackageManagerException e) {
+                // Session is sealed but could not be verified, we need to destroy it
+                destroyInternal();
+                dispatchSessionFinished(e.error, ExceptionUtils.getCompleteMessage(e), null);
+
                 throw new IllegalArgumentException("Package is not valid", e);
             }
 
@@ -1539,6 +1579,10 @@
      */
     void write(@NonNull XmlSerializer out, @NonNull File sessionsDir) throws IOException {
         synchronized (mLock) {
+            if (mDestroyed) {
+                return;
+            }
+
             out.startTag(null, TAG_SESSION);
 
             writeIntAttribute(out, ATTR_SESSION_ID, sessionId);
diff --git a/services/core/java/com/android/server/pm/PackageManagerException.java b/services/core/java/com/android/server/pm/PackageManagerException.java
index 0e3f173..0793b09 100644
--- a/services/core/java/com/android/server/pm/PackageManagerException.java
+++ b/services/core/java/com/android/server/pm/PackageManagerException.java
@@ -40,6 +40,11 @@
         this.error = error;
     }
 
+    public PackageManagerException(Throwable e) {
+        super(e);
+        this.error = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+    }
+
     public static PackageManagerException from(PackageParserException e)
             throws PackageManagerException {
         throw new PackageManagerException(e.error, e.getMessage(), e.getCause());
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 20fb350..d129118 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -577,8 +577,9 @@
     public static final int REASON_BACKGROUND_DEXOPT = 3;
     public static final int REASON_AB_OTA = 4;
     public static final int REASON_INACTIVE_PACKAGE_DOWNGRADE = 5;
+    public static final int REASON_SHARED = 6;
 
-    public static final int REASON_LAST = REASON_INACTIVE_PACKAGE_DOWNGRADE;
+    public static final int REASON_LAST = REASON_SHARED;
 
     /** All dangerous permission names in the same order as the events in MetricsEvent */
     private static final List<String> ALL_DANGEROUS_PERMISSIONS = Arrays.asList(
@@ -2711,8 +2712,14 @@
                         // Actual deletion of code and data will be handled by later
                         // reconciliation step
                     } else {
-                        final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
-                        if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
+                        // we still have a disabled system package, but, it still might have
+                        // been removed. check the code path still exists and check there's
+                        // still a package. the latter can happen if an OTA keeps the same
+                        // code path, but, changes the package name.
+                        final PackageSetting disabledPs =
+                                mSettings.getDisabledSystemPkgLPr(ps.name);
+                        if (disabledPs.codePath == null || !disabledPs.codePath.exists()
+                                || disabledPs.pkg == null) {
                             possiblyDeletedUpdatedSystemApps.add(ps.name);
                         }
                     }
@@ -8512,7 +8519,7 @@
                         continue;
                     }
                     if (filterAppAccessLPr(ps, callingUid, userId)) {
-                        return null;
+                        continue;
                     }
                     final PackageInfo pi = generatePackageInfo(ps, flags, userId);
                     if (pi != null) {
@@ -8527,7 +8534,7 @@
                         continue;
                     }
                     if (filterAppAccessLPr(ps, callingUid, userId)) {
-                        return null;
+                        continue;
                     }
                     final PackageInfo pi = generatePackageInfo((PackageSetting)
                             p.mExtras, flags, userId);
@@ -8639,7 +8646,7 @@
                             continue;
                         }
                         if (filterAppAccessLPr(ps, callingUid, userId)) {
-                            return null;
+                            continue;
                         }
                         ai = PackageParser.generateApplicationInfo(ps.pkg, effectiveFlags,
                                 ps.readUserState(userId), userId);
@@ -8665,7 +8672,7 @@
                             continue;
                         }
                         if (filterAppAccessLPr(ps, callingUid, userId)) {
-                            return null;
+                            continue;
                         }
                         ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
                                 ps.readUserState(userId), userId);
@@ -11398,6 +11405,10 @@
                                     + " but expected at " + known.codePathString
                                     + "; ignoring.");
                         }
+                    } else {
+                        throw new PackageManagerException(INSTALL_FAILED_INVALID_INSTALL_LOCATION,
+                                "Application package " + pkg.packageName
+                                + " not found; ignoring.");
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
index 1a97a72..19b0d9b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
@@ -26,14 +26,19 @@
 public class PackageManagerServiceCompilerMapping {
     // Names for compilation reasons.
     static final String REASON_STRINGS[] = {
-            "first-boot", "boot", "install", "bg-dexopt", "ab-ota", "inactive"
+            "first-boot", "boot", "install", "bg-dexopt", "ab-ota", "inactive", "shared"
     };
 
+    static final int REASON_SHARED_INDEX = 6;
+
     // Static block to ensure the strings array is of the right length.
     static {
         if (PackageManagerService.REASON_LAST + 1 != REASON_STRINGS.length) {
             throw new IllegalStateException("REASON_STRINGS not correct");
         }
+        if (!"shared".equals(REASON_STRINGS[REASON_SHARED_INDEX])) {
+            throw new IllegalStateException("REASON_STRINGS not correct because of shared index");
+        }
     }
 
     private static String getSystemPropertyName(int reason) {
@@ -52,11 +57,18 @@
                 !DexFile.isValidCompilerFilter(sysPropValue)) {
             throw new IllegalStateException("Value \"" + sysPropValue +"\" not valid "
                     + "(reason " + REASON_STRINGS[reason] + ")");
+        } else if (!isFilterAllowedForReason(reason, sysPropValue)) {
+            throw new IllegalStateException("Value \"" + sysPropValue +"\" not allowed "
+                    + "(reason " + REASON_STRINGS[reason] + ")");
         }
 
         return sysPropValue;
     }
 
+    private static boolean isFilterAllowedForReason(int reason, String filter) {
+        return reason != REASON_SHARED_INDEX || !DexFile.isProfileGuidedCompilerFilter(filter);
+    }
+
     // Check that the properties are set and valid.
     // Note: this is done in a separate method so this class can be statically initialized.
     static void checkProperties() {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index e6c6622..48d6cdc 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -128,6 +128,7 @@
  *
  * Method naming convention:
  * <ul>
+ * <li> Methods suffixed with "LAr" should be called within the {@link #mAppRestrictionsLock} lock.
  * <li> Methods suffixed with "LP" should be called within the {@link #mPackagesLock} lock.
  * <li> Methods suffixed with "LR" should be called within the {@link #mRestrictionsLock} lock.
  * <li> Methods suffixed with "LU" should be called within the {@link #mUsersLock} lock.
@@ -232,6 +233,8 @@
     // Short-term lock for internal state, when interaction/sync with PM is not required
     private final Object mUsersLock = LockGuard.installNewLock(LockGuard.INDEX_USER);
     private final Object mRestrictionsLock = new Object();
+    // Used for serializing access to app restriction files
+    private final Object mAppRestrictionsLock = new Object();
 
     private final Handler mHandler;
 
@@ -2328,13 +2331,11 @@
     /**
      * Removes the app restrictions file for a specific package and user id, if it exists.
      */
-    private void cleanAppRestrictionsForPackage(String pkg, int userId) {
-        synchronized (mPackagesLock) {
-            File dir = Environment.getUserSystemDirectory(userId);
-            File resFile = new File(dir, packageToRestrictionsFileName(pkg));
-            if (resFile.exists()) {
-                resFile.delete();
-            }
+    private static void cleanAppRestrictionsForPackageLAr(String pkg, int userId) {
+        File dir = Environment.getUserSystemDirectory(userId);
+        File resFile = new File(dir, packageToRestrictionsFileName(pkg));
+        if (resFile.exists()) {
+            resFile.delete();
         }
     }
 
@@ -2853,9 +2854,9 @@
                 || !UserHandle.isSameApp(Binder.getCallingUid(), getUidForPackage(packageName))) {
             checkSystemOrRoot("get application restrictions for other user/app " + packageName);
         }
-        synchronized (mPackagesLock) {
+        synchronized (mAppRestrictionsLock) {
             // Read the restrictions from XML
-            return readApplicationRestrictionsLP(packageName, userId);
+            return readApplicationRestrictionsLAr(packageName, userId);
         }
     }
 
@@ -2866,12 +2867,12 @@
         if (restrictions != null) {
             restrictions.setDefusable(true);
         }
-        synchronized (mPackagesLock) {
+        synchronized (mAppRestrictionsLock) {
             if (restrictions == null || restrictions.isEmpty()) {
-                cleanAppRestrictionsForPackage(packageName, userId);
+                cleanAppRestrictionsForPackageLAr(packageName, userId);
             } else {
                 // Write the restrictions to XML
-                writeApplicationRestrictionsLP(packageName, restrictions, userId);
+                writeApplicationRestrictionsLAr(packageName, restrictions, userId);
             }
         }
 
@@ -2894,15 +2895,17 @@
         }
     }
 
-    private Bundle readApplicationRestrictionsLP(String packageName, int userId) {
+    @GuardedBy("mAppRestrictionsLock")
+    private static Bundle readApplicationRestrictionsLAr(String packageName, int userId) {
         AtomicFile restrictionsFile =
                 new AtomicFile(new File(Environment.getUserSystemDirectory(userId),
                         packageToRestrictionsFileName(packageName)));
-        return readApplicationRestrictionsLP(restrictionsFile);
+        return readApplicationRestrictionsLAr(restrictionsFile);
     }
 
     @VisibleForTesting
-    static Bundle readApplicationRestrictionsLP(AtomicFile restrictionsFile) {
+    @GuardedBy("mAppRestrictionsLock")
+    static Bundle readApplicationRestrictionsLAr(AtomicFile restrictionsFile) {
         final Bundle restrictions = new Bundle();
         final ArrayList<String> values = new ArrayList<>();
         if (!restrictionsFile.getBaseFile().exists()) {
@@ -2985,16 +2988,18 @@
         return childBundle;
     }
 
-    private void writeApplicationRestrictionsLP(String packageName,
+    @GuardedBy("mAppRestrictionsLock")
+    private static void writeApplicationRestrictionsLAr(String packageName,
             Bundle restrictions, int userId) {
         AtomicFile restrictionsFile = new AtomicFile(
                 new File(Environment.getUserSystemDirectory(userId),
                         packageToRestrictionsFileName(packageName)));
-        writeApplicationRestrictionsLP(restrictions, restrictionsFile);
+        writeApplicationRestrictionsLAr(restrictions, restrictionsFile);
     }
 
     @VisibleForTesting
-    static void writeApplicationRestrictionsLP(Bundle restrictions, AtomicFile restrictionsFile) {
+    @GuardedBy("mAppRestrictionsLock")
+    static void writeApplicationRestrictionsLAr(Bundle restrictions, AtomicFile restrictionsFile) {
         FileOutputStream fos = null;
         try {
             fos = restrictionsFile.startWrite();
@@ -3238,7 +3243,7 @@
         return -1;
     }
 
-    private String packageToRestrictionsFileName(String packageName) {
+    private static String packageToRestrictionsFileName(String packageName) {
         return RESTRICTIONS_FILE_PREFIX + packageName + XML_SUFFIX;
     }
 
diff --git a/services/core/java/com/android/server/pm/dex/DexoptUtils.java b/services/core/java/com/android/server/pm/dex/DexoptUtils.java
index 0196212..e1310a2 100644
--- a/services/core/java/com/android/server/pm/dex/DexoptUtils.java
+++ b/services/core/java/com/android/server/pm/dex/DexoptUtils.java
@@ -21,6 +21,7 @@
 import android.util.SparseArray;
 
 import com.android.internal.os.ClassLoaderFactory;
+import com.android.server.pm.PackageDexOptimizer;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -35,7 +36,9 @@
     /**
      * Creates the class loader context dependencies for each of the application code paths.
      * The returned array contains the class loader contexts that needs to be passed to dexopt in
-     * order to ensure correct optimizations.
+     * order to ensure correct optimizations. "Code" paths with no actual code, as specified by
+     * {@param pathsWithCode}, are ignored and will have null as their context in the returned array
+     * (configuration splits are an example of paths without code).
      *
      * A class loader context describes how the class loader chain should be built by dex2oat
      * in order to ensure that classes are resolved during compilation as they would be resolved
@@ -60,7 +63,8 @@
      * {@link android.app.LoadedApk#makePaths(
      * android.app.ActivityThread, boolean, ApplicationInfo, List, List)}.
      */
-    public static String[] getClassLoaderContexts(ApplicationInfo info, String[] sharedLibraries) {
+    public static String[] getClassLoaderContexts(ApplicationInfo info,
+            String[] sharedLibraries, boolean[] pathsWithCode) {
         // The base class loader context contains only the shared library.
         String sharedLibrariesClassPath = encodeClasspath(sharedLibraries);
         String baseApkContextClassLoader = encodeClassLoader(
@@ -86,7 +90,7 @@
         // Index 0 is the class loaded context for the base apk.
         // Index `i` is the class loader context encoding for split `i`.
         String[] classLoaderContexts = new String[/*base apk*/ 1 + splitRelativeCodePaths.length];
-        classLoaderContexts[0] = baseApkContextClassLoader;
+        classLoaderContexts[0] = pathsWithCode[0] ? baseApkContextClassLoader : null;
 
         if (!info.requestsIsolatedSplitLoading() || info.splitDependencies == null) {
             // If the app didn't request for the splits to be loaded in isolation or if it does not
@@ -94,7 +98,15 @@
             // apk class loader (in the order of their definition).
             String classpath = sharedLibrariesAndBaseClassPath;
             for (int i = 1; i < classLoaderContexts.length; i++) {
-                classLoaderContexts[i] = encodeClassLoader(classpath, info.classLoaderName);
+                classLoaderContexts[i] = pathsWithCode[i]
+                        ? encodeClassLoader(classpath, info.classLoaderName) : null;
+                // Note that the splits with no code are not removed from the classpath computation.
+                // i.e. split_n might get the split_n-1 in its classpath dependency even
+                // if split_n-1 has no code.
+                // The splits with no code do not matter for the runtime which ignores
+                // apks without code when doing the classpath checks. As such we could actually
+                // filter them but we don't do it in order to keep consistency with how the apps
+                // are loaded.
                 classpath = encodeClasspath(classpath, splitRelativeCodePaths[i - 1]);
             }
         } else {
@@ -116,9 +128,17 @@
             String splitDependencyOnBase = encodeClassLoader(
                     sharedLibrariesAndBaseClassPath, info.classLoaderName);
             SparseArray<int[]> splitDependencies = info.splitDependencies;
+
+            // Note that not all splits have dependencies (e.g. configuration splits)
+            // The splits without dependencies will have classLoaderContexts[config_split_index]
+            // set to null after this step.
             for (int i = 1; i < splitDependencies.size(); i++) {
-                getParentDependencies(splitDependencies.keyAt(i), splitClassLoaderEncodingCache,
-                        splitDependencies, classLoaderContexts, splitDependencyOnBase);
+                int splitIndex = splitDependencies.keyAt(i);
+                if (pathsWithCode[splitIndex]) {
+                    // Compute the class loader context only for the splits with code.
+                    getParentDependencies(splitIndex, splitClassLoaderEncodingCache,
+                            splitDependencies, classLoaderContexts, splitDependencyOnBase);
+                }
             }
 
             // At this point classLoaderContexts contains only the parent dependencies.
@@ -126,8 +146,17 @@
             // come first in the context.
             for (int i = 1; i < classLoaderContexts.length; i++) {
                 String splitClassLoader = encodeClassLoader("", info.splitClassLoaderNames[i - 1]);
-                classLoaderContexts[i] = encodeClassLoaderChain(
-                        splitClassLoader, classLoaderContexts[i]);
+                if (pathsWithCode[i]) {
+                    // If classLoaderContexts[i] is null it means that the split does not have
+                    // any dependency. In this case its context equals its declared class loader.
+                    classLoaderContexts[i] = classLoaderContexts[i] == null
+                            ? splitClassLoader
+                            : encodeClassLoaderChain(splitClassLoader, classLoaderContexts[i]);
+                } else {
+                    // This is a split without code, it has no dependency and it is not compiled.
+                    // Its context will be null.
+                    classLoaderContexts[i] = null;
+                }
             }
         }
 
@@ -210,10 +239,15 @@
     /**
      * Encodes a single class loader dependency starting from {@param path} and
      * {@param classLoaderName}.
+     * When classpath is {@link PackageDexOptimizer#SKIP_SHARED_LIBRARY_CHECK}, the method returns
+     * the same. This special property is used only during OTA.
      * NOTE: Keep this in sync with the dexopt expectations! Right now that is either "PCL[path]"
      * for a PathClassLoader or "DLC[path]" for a DelegateLastClassLoader.
      */
-    private static String encodeClassLoader(String classpath, String classLoaderName) {
+    /*package*/ static String encodeClassLoader(String classpath, String classLoaderName) {
+        if (classpath.equals(PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK)) {
+            return classpath;
+        }
         String classLoaderDexoptEncoding = classLoaderName;
         if (ClassLoaderFactory.isPathClassLoaderName(classLoaderName)) {
             classLoaderDexoptEncoding = "PCL";
@@ -227,10 +261,17 @@
 
     /**
      * Links to dependencies together in a format accepted by dexopt.
+     * For the special case when either of cl1 or cl2 equals
+     * {@link PackageDexOptimizer#SKIP_SHARED_LIBRARY_CHECK}, the method returns the same. This
+     * property is used only during OTA.
      * NOTE: Keep this in sync with the dexopt expectations! Right now that is a list of split
      * dependencies {@see encodeClassLoader} separated by ';'.
      */
-    private static String encodeClassLoaderChain(String cl1, String cl2) {
+    /*package*/ static String encodeClassLoaderChain(String cl1, String cl2) {
+        if (cl1.equals(PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK) ||
+                cl2.equals(PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK)) {
+            return PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK;
+        }
         if (cl1.isEmpty()) return cl2;
         if (cl2.isEmpty()) return cl1;
         return cl1 + ";" + cl2;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 27159fa..bc531c3 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -335,6 +335,7 @@
     static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
     static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
     static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";
+    static public final String SYSTEM_DIALOG_REASON_SCREENSHOT = "screenshot";
 
     /**
      * These are the system UI flags that, when changing, can cause the layout
@@ -829,6 +830,7 @@
     private static final int MSG_ACCESSIBILITY_TV = 23;
     private static final int MSG_DISPATCH_BACK_KEY_TO_AUTOFILL = 24;
     private static final int MSG_SYSTEM_KEY_PRESS = 25;
+    private static final int MSG_HANDLE_ALL_APPS = 26;
 
     private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
     private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
@@ -921,6 +923,9 @@
                 case MSG_SYSTEM_KEY_PRESS:
                     sendSystemKeyToStatusBar(msg.arg1);
                     break;
+                case MSG_HANDLE_ALL_APPS:
+                    launchAllAppsAction();
+                    break;
             }
         }
     }
@@ -1801,6 +1806,17 @@
 
     private void launchAllAppsAction() {
         Intent intent = new Intent(Intent.ACTION_ALL_APPS);
+        if (mHasFeatureLeanback) {
+            final PackageManager pm = mContext.getPackageManager();
+            Intent intentLauncher = new Intent(Intent.ACTION_MAIN);
+            intentLauncher.addCategory(Intent.CATEGORY_HOME);
+            ResolveInfo resolveInfo = pm.resolveActivityAsUser(intentLauncher,
+                    PackageManager.MATCH_SYSTEM_ONLY,
+                    mCurrentUserId);
+            if (resolveInfo != null) {
+                intent.setPackage(resolveInfo.activityInfo.packageName);
+            }
+        }
         startActivityAsUser(intent, UserHandle.CURRENT);
     }
 
@@ -3620,6 +3636,14 @@
             return -1;
         } else if (mHasFeatureLeanback && interceptAccessibilityGestureTv(keyCode, down)) {
             return -1;
+        } else if (keyCode == KeyEvent.KEYCODE_ALL_APPS) {
+            if (!down) {
+                mHandler.removeMessages(MSG_HANDLE_ALL_APPS);
+                Message msg = mHandler.obtainMessage(MSG_HANDLE_ALL_APPS);
+                msg.setAsynchronous(true);
+                msg.sendToTarget();
+            }
+            return -1;
         }
 
         // Toggle Caps Lock on META-ALT.
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 50e5e7b..5a5471b 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -1,5 +1,7 @@
 package com.android.server.policy.keyguard;
 
+import static android.view.Display.INVALID_DISPLAY;
+
 import android.app.ActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -201,7 +203,10 @@
             mKeyguardState.reset();
             mHandler.post(() -> {
                 try {
-                    ActivityManager.getService().setLockScreenShown(true);
+                    // There are no longer any keyguard windows on secondary displays, so pass
+                    // INVALID_DISPLAY. All that means is that showWhenLocked activities on
+                    // secondary displays now get to show.
+                    ActivityManager.getService().setLockScreenShown(true, INVALID_DISPLAY);
                 } catch (RemoteException e) {
                     // Local call.
                 }
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 0c72326..be44607 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -120,7 +120,7 @@
         implements Watchdog.Monitor {
     private static final String TAG = "PowerManagerService";
 
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = true;
     private static final boolean DEBUG_SPEW = DEBUG && true;
 
     // Message: Sent when a user activity timeout occurs to update the power state.
@@ -1569,12 +1569,15 @@
         return true;
     }
 
-    private void setWakefulnessLocked(int wakefulness, int reason) {
+    @VisibleForTesting
+    void setWakefulnessLocked(int wakefulness, int reason) {
         if (mWakefulness != wakefulness) {
             mWakefulness = wakefulness;
             mWakefulnessChanging = true;
             mDirty |= DIRTY_WAKEFULNESS;
-            mNotifier.onWakefulnessChangeStarted(wakefulness, reason);
+            if (mNotifier != null) {
+                mNotifier.onWakefulnessChangeStarted(wakefulness, reason);
+            }
         }
     }
 
@@ -2432,11 +2435,8 @@
         return value >= -1.0f && value <= 1.0f;
     }
 
-    private int getDesiredScreenPolicyLocked() {
-        if (mIsVrModeEnabled) {
-            return DisplayPowerRequest.POLICY_VR;
-        }
-
+    @VisibleForTesting
+    int getDesiredScreenPolicyLocked() {
         if (mWakefulness == WAKEFULNESS_ASLEEP || sQuiescent) {
             return DisplayPowerRequest.POLICY_OFF;
         }
@@ -2452,6 +2452,13 @@
             // doze after screen off.  This causes the screen off transition to be skipped.
         }
 
+        // It is important that POLICY_VR check happens after the wakefulness checks above so
+        // that VR-mode does not prevent displays from transitioning to the correct state when
+        // dozing or sleeping.
+        if (mIsVrModeEnabled) {
+            return DisplayPowerRequest.POLICY_VR;
+        }
+
         if ((mWakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0
                 || (mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0
                 || !mBootCompleted
@@ -3113,6 +3120,11 @@
         }
     }
 
+    @VisibleForTesting
+    void setVrModeEnabled(boolean enabled) {
+        mIsVrModeEnabled = enabled;
+    }
+
     private void powerHintInternal(int hintId, int data) {
         nativeSendPowerHint(hintId, data);
     }
@@ -3810,7 +3822,7 @@
 
             synchronized (mLock) {
                 if (mIsVrModeEnabled != enabled) {
-                    mIsVrModeEnabled = enabled;
+                    setVrModeEnabled(enabled);
                     mDirty |= DIRTY_VR_MODE_CHANGED;
                     updatePowerStateLocked();
                 }
diff --git a/services/core/java/com/android/server/search/SearchManagerService.java b/services/core/java/com/android/server/search/SearchManagerService.java
index 8969771..c3fa823 100644
--- a/services/core/java/com/android/server/search/SearchManagerService.java
+++ b/services/core/java/com/android/server/search/SearchManagerService.java
@@ -17,7 +17,6 @@
 package com.android.server.search;
 
 import android.app.ActivityManager;
-import android.app.AppGlobals;
 import android.app.IActivityManager;
 import android.app.ISearchManager;
 import android.app.SearchManager;
@@ -26,7 +25,6 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.database.ContentObserver;
@@ -37,6 +35,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.service.voice.VoiceInteractionService;
 import android.util.Log;
 import android.util.SparseArray;
 
@@ -272,24 +271,25 @@
         }
     }
 
+    // Check and return VIS component
     private ComponentName getLegacyAssistComponent(int userHandle) {
         try {
             userHandle = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
-                    Binder.getCallingUid(), userHandle, true, false, "getLegacyAssistComponent", null);
-            IPackageManager pm = AppGlobals.getPackageManager();
-            Intent assistIntent = new Intent(Intent.ACTION_ASSIST);
-            ResolveInfo info =
-                    pm.resolveIntent(assistIntent,
-                            assistIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                            PackageManager.MATCH_DEFAULT_ONLY, userHandle);
-            if (info != null) {
+                    Binder.getCallingUid(), userHandle, true, false, "getLegacyAssistComponent",
+                    null);
+            PackageManager pm = mContext.getPackageManager();
+            Intent intentAssistProbe = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
+            List<ResolveInfo> infoListVis = pm.queryIntentServicesAsUser(intentAssistProbe,
+                    PackageManager.MATCH_SYSTEM_ONLY, userHandle);
+            if (infoListVis == null || infoListVis.isEmpty()) {
+                return null;
+            } else {
+                ResolveInfo rInfo = infoListVis.get(0);
                 return new ComponentName(
-                        info.activityInfo.applicationInfo.packageName,
-                        info.activityInfo.name);
+                        rInfo.serviceInfo.applicationInfo.packageName,
+                        rInfo.serviceInfo.name);
+
             }
-        } catch (RemoteException re) {
-            // Local call
-            Log.e(TAG, "RemoteException in getLegacyAssistComponent: " + re);
         } catch (Exception e) {
             Log.e(TAG, "Exception in getLegacyAssistComponent: " + e);
         }
@@ -304,9 +304,15 @@
         }
         long ident = Binder.clearCallingIdentity();
         try {
-            Intent intent = new Intent(Intent.ACTION_ASSIST);
+            Intent intent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
             intent.setComponent(comp);
+
             IActivityManager am = ActivityManager.getService();
+            if (args != null) {
+                args.putInt(Intent.EXTRA_KEY_EVENT, android.view.KeyEvent.KEYCODE_ASSIST);
+            }
+            intent.putExtras(args);
+
             return am.launchAssistIntent(intent, ActivityManager.ASSIST_CONTEXT_BASIC, hint,
                     userHandle, args);
         } catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/timezone/IntentHelperImpl.java b/services/core/java/com/android/server/timezone/IntentHelperImpl.java
index 11928b9..6db70cd 100644
--- a/services/core/java/com/android/server/timezone/IntentHelperImpl.java
+++ b/services/core/java/com/android/server/timezone/IntentHelperImpl.java
@@ -53,20 +53,34 @@
         // The intent filter that triggers when package update events happen that indicate there may
         // be work to do.
         IntentFilter packageIntentFilter = new IntentFilter();
-        // Either of these mean a downgrade?
-        packageIntentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
-        packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
+
         packageIntentFilter.addDataScheme("package");
         packageIntentFilter.addDataSchemeSpecificPart(
                 updaterAppPackageName, PatternMatcher.PATTERN_LITERAL);
         packageIntentFilter.addDataSchemeSpecificPart(
                 dataAppPackageName, PatternMatcher.PATTERN_LITERAL);
+
+        // ACTION_PACKAGE_ADDED is fired when a package is upgraded or downgraded (in addition to
+        // ACTION_PACKAGE_REMOVED and ACTION_PACKAGE_REPLACED). A system/priv-app can never be
+        // removed entirely so we do not need to trigger on ACTION_PACKAGE_REMOVED or
+        // ACTION_PACKAGE_FULLY_REMOVED.
+        packageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+
+        // ACTION_PACKAGE_CHANGED is used when a package is disabled / re-enabled. It is not
+        // strictly necessary to trigger on this but it won't hurt anything and may catch some cases
+        // where a package has changed while disabled.
+        // Note: ACTION_PACKAGE_CHANGED is not fired when updating a suspended app, but
+        // ACTION_PACKAGE_ADDED, ACTION_PACKAGE_REMOVED and ACTION_PACKAGE_REPLACED are (and the app
+        // is left in an unsuspended state after this).
+        packageIntentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+
+        // We do not register for ACTION_PACKAGE_RESTARTED because it doesn't imply an update.
+        // We do not register for ACTION_PACKAGE_DATA_CLEARED because the updater / data apps are
+        // not expected to need local data.
+
         Receiver packageUpdateReceiver = new Receiver(listener, true /* packageUpdated */);
         mContext.registerReceiver(packageUpdateReceiver, packageIntentFilter);
 
-        // TODO(nfuller): Add more exotic intents as needed. e.g.
-        // packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
-        // Also, disabled...?
         mReliabilityReceiver = new Receiver(listener, false /* packageUpdated */);
     }
 
diff --git a/services/core/java/com/android/server/timezone/RulesManagerService.java b/services/core/java/com/android/server/timezone/RulesManagerService.java
index 50f27ed..3ad4419 100644
--- a/services/core/java/com/android/server/timezone/RulesManagerService.java
+++ b/services/core/java/com/android/server/timezone/RulesManagerService.java
@@ -343,16 +343,20 @@
         @Override
         public void run() {
             EventLogTags.writeTimezoneUninstallStarted(toStringOrNull(mCheckToken));
-            boolean success = false;
+            boolean packageTrackerStatus = false;
             try {
-                success = mInstaller.stageUninstall();
-                // Right now we just have success (0) / failure (1). All clients should be checking
-                // against SUCCESS. More granular failures may be added in future.
-                int resultCode = success ? Callback.SUCCESS
-                        : Callback.ERROR_UNKNOWN_FAILURE;
+                int uninstallResult = mInstaller.stageUninstall();
+                packageTrackerStatus = (uninstallResult == TimeZoneDistroInstaller.UNINSTALL_SUCCESS
+                        || uninstallResult == TimeZoneDistroInstaller.UNINSTALL_NOTHING_INSTALLED);
+
+                // Right now we just have Callback.SUCCESS / Callback.ERROR_UNKNOWN_FAILURE for
+                // uninstall. All clients should be checking against SUCCESS. More granular failures
+                // may be added in future.
+                int callbackResultCode =
+                        packageTrackerStatus ? Callback.SUCCESS : Callback.ERROR_UNKNOWN_FAILURE;
                 EventLogTags.writeTimezoneUninstallComplete(
-                        toStringOrNull(mCheckToken), resultCode);
-                sendFinishedStatus(mCallback, resultCode);
+                        toStringOrNull(mCheckToken), callbackResultCode);
+                sendFinishedStatus(mCallback, callbackResultCode);
             } catch (Exception e) {
                 EventLogTags.writeTimezoneUninstallComplete(
                         toStringOrNull(mCheckToken), Callback.ERROR_UNKNOWN_FAILURE);
@@ -360,7 +364,7 @@
                 sendFinishedStatus(mCallback, Callback.ERROR_UNKNOWN_FAILURE);
             } finally {
                 // Notify the package tracker that the operation is now complete.
-                mPackageTracker.recordCheckResult(mCheckToken, success);
+                mPackageTracker.recordCheckResult(mCheckToken, packageTrackerStatus);
 
                 mOperationInProgress.set(false);
             }
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index b963561..b888ec2 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -1138,7 +1138,13 @@
         mMonitor = new MyPackageMonitor();
         mMonitor.register(context, null, UserHandle.ALL, true);
         getWallpaperDir(UserHandle.USER_SYSTEM).mkdirs();
+
+        // Initialize state from the persistent store, then guarantee that the
+        // WallpaperData for the system imagery is instantiated & active, creating
+        // it from defaults if necessary.
         loadSettingsLocked(UserHandle.USER_SYSTEM, false);
+        getWallpaperSafeLocked(UserHandle.USER_SYSTEM, FLAG_SYSTEM);
+
         mColorsChangedListeners = new SparseArray<>();
     }
 
@@ -1295,15 +1301,13 @@
     }
 
     void switchUser(int userId, IRemoteCallback reply) {
-        WallpaperData systemWallpaper;
-        WallpaperData lockWallpaper;
+        final WallpaperData systemWallpaper;
+        final WallpaperData lockWallpaper;
         synchronized (mLock) {
             mCurrentUserId = userId;
             systemWallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
-            lockWallpaper = mLockWallpaperMap.get(userId);
-            if (lockWallpaper == null) {
-                lockWallpaper = systemWallpaper;
-            }
+            final WallpaperData tmpLockWallpaper = mLockWallpaperMap.get(userId);
+            lockWallpaper = tmpLockWallpaper == null ? systemWallpaper : tmpLockWallpaper;
             // Not started watching yet, in case wallpaper data was loaded for other reasons.
             if (systemWallpaper.wallpaperObserver == null) {
                 systemWallpaper.wallpaperObserver = new WallpaperObserver(systemWallpaper);
@@ -1311,8 +1315,13 @@
             }
             switchWallpaper(systemWallpaper, reply);
         }
-        notifyWallpaperColorsChanged(systemWallpaper, FLAG_SYSTEM);
-        notifyWallpaperColorsChanged(lockWallpaper, FLAG_LOCK);
+
+        // Offload color extraction to another thread since switchUser will be called
+        // from the main thread.
+        FgThread.getHandler().post(() -> {
+            notifyWallpaperColorsChanged(systemWallpaper, FLAG_SYSTEM);
+            notifyWallpaperColorsChanged(lockWallpaper, FLAG_LOCK);
+        });
     }
 
     void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) {
@@ -1627,13 +1636,10 @@
                     (which == FLAG_LOCK) ? mLockWallpaperMap : mWallpaperMap;
             WallpaperData wallpaper = whichSet.get(wallpaperUserId);
             if (wallpaper == null) {
-                // common case, this is the first lookup post-boot of the system or
-                // unified lock, so we bring up the saved state lazily now and recheck.
-                loadSettingsLocked(wallpaperUserId, false);
-                wallpaper = whichSet.get(wallpaperUserId);
-                if (wallpaper == null) {
-                    return null;
-                }
+                // There is no established wallpaper imagery of this type (expected
+                // only for lock wallpapers; a system WallpaperData is established at
+                // user switch)
+                return null;
             }
             try {
                 if (outParams != null) {
@@ -1658,7 +1664,7 @@
     @Override
     public WallpaperInfo getWallpaperInfo(int userId) {
         userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
-                Binder.getCallingUid(), userId, false, true, "getWallpaperIdForUser", null);
+                Binder.getCallingUid(), userId, false, true, "getWallpaperInfo", null);
         synchronized (mLock) {
             WallpaperData wallpaper = mWallpaperMap.get(userId);
             if (wallpaper != null && wallpaper.connection != null) {
@@ -2260,7 +2266,7 @@
     private void writeWallpaperAttributes(XmlSerializer out, String tag, WallpaperData wallpaper)
             throws IllegalArgumentException, IllegalStateException, IOException {
         if (DEBUG) {
-            Slog.v(TAG, "writeWallpaperAttributes");
+            Slog.v(TAG, "writeWallpaperAttributes id=" + wallpaper.wallpaperId);
         }
         out.startTag(null, tag);
         out.attribute(null, "id", Integer.toString(wallpaper.wallpaperId));
@@ -2359,6 +2365,9 @@
      * the event yet.  We use this safe method when we don't care about this ordering and just
      * want to update the data.  The data is going to be applied when the user switch observer
      * is eventually executed.
+     *
+     * Important: this method loads settings to initialize the given user's wallpaper data if
+     * there is no current in-memory state.
      */
     private WallpaperData getWallpaperSafeLocked(int userId, int which) {
         // We're setting either just system (work with the system wallpaper),
@@ -2397,8 +2406,6 @@
     }
 
     private void loadSettingsLocked(int userId, boolean keepDimensionHints) {
-        if (DEBUG) Slog.v(TAG, "loadSettingsLocked");
-
         JournaledFile journal = makeJournaledFile(userId);
         FileInputStream stream = null;
         File file = journal.chooseForRead();
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 5cd4fc4..37695cb 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3020,7 +3020,7 @@
                 final boolean foundTargetWs =
                         (w.mAppToken != null && w.mAppToken.token == appToken)
                                 || (mScreenshotApplicationState.appWin != null && wallpaperOnly);
-                if (foundTargetWs && winAnim.getShown()) {
+                if (foundTargetWs && winAnim.getShown() && winAnim.mLastAlpha > 0f) {
                     mScreenshotApplicationState.screenshotReady = true;
                 }
 
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index ecf9067..6c11d8b 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -299,7 +299,7 @@
 
         return new TaskSnapshot(hwBitmap.createGraphicBufferHandle(),
                 topChild.getConfiguration().orientation, mainWindow.mStableInsets,
-                false /* reduced */, 1.0f /* scale */);
+                ActivityManager.isLowRamDeviceStatic() /* reduced */, 1.0f /* scale */);
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index df0dfcb..28dba73 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1484,7 +1484,7 @@
     // TODO: Another visibility method that was added late in the release to minimize risk.
     @Override
     public boolean canAffectSystemUiFlags() {
-        final boolean shown = mWinAnimator.getShown() && mWinAnimator.mShownAlpha > 0f;
+        final boolean shown = mWinAnimator.getShown();
 
         // We only consider the app to be exiting when the animation has started. After the app
         // transition is executed the windows are marked exiting before the new windows have been
@@ -1498,7 +1498,12 @@
 
         final boolean exiting = exitingSelf || mDestroying || appExiting;
         final boolean translucent = mAttrs.alpha == 0.0f;
-        return shown && !exiting && !translucent;
+
+        // If we are entering with a dummy animation, avoid affecting SystemUI flags until the
+        // transition is starting.
+        final boolean enteringWithDummyAnimation =
+                mWinAnimator.isDummyAnimation() && mWinAnimator.mShownAlpha == 0f;
+        return shown && !exiting && !translucent && !enteringWithDummyAnimation;
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index dd887e0..64ac7ac 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1657,7 +1657,14 @@
                     if (mWin.mAppToken != null) {
                         mWin.mAppToken.setCanTurnScreenOn(false);
                     }
-                    mAnimator.mBulkUpdateParams |= SET_TURN_ON_SCREEN;
+
+                    // We do not add {@code SET_TURN_ON_SCREEN} when the screen is already
+                    // interactive as the value may persist until the next animation, which could
+                    // potentially occurring while turning off the screen. This would lead to the
+                    // screen incorrectly turning back on.
+                    if (!mService.mPowerManager.isInteractive()) {
+                        mAnimator.mBulkUpdateParams |= SET_TURN_ON_SCREEN;
+                    }
                 }
             }
             if (hasSurface()) {
diff --git a/services/core/jni/BroadcastRadio/NativeCallbackThread.cpp b/services/core/jni/BroadcastRadio/NativeCallbackThread.cpp
index 85ec9e0..81d46f3 100644
--- a/services/core/jni/BroadcastRadio/NativeCallbackThread.cpp
+++ b/services/core/jni/BroadcastRadio/NativeCallbackThread.cpp
@@ -48,15 +48,19 @@
         return;
     }
 
-    while (!mExiting) {
-        ALOGV("Waiting for task...");
+    while (true) {
         Task task;
         {
             unique_lock<mutex> lk(mQueueMutex);
-            mQueueCond.wait(lk);
-            if (mExiting) break;
 
-            if (mQueue.empty()) continue;
+            if (mExiting) break;
+            if (mQueue.empty()) {
+                ALOGV("Waiting for task...");
+                mQueueCond.wait(lk);
+                if (mExiting) break;
+                if (mQueue.empty()) continue;
+            }
+
             task = mQueue.front();
             mQueue.pop();
         }
@@ -74,6 +78,7 @@
     ALOGE_IF(res != JNI_OK, "Couldn't detach thread");
 
     ALOGV("Native callback thread %p finished", this);
+    ALOGD_IF(!mQueue.empty(), "Skipped execution of %zu tasks", mQueue.size());
 }
 
 void NativeCallbackThread::enqueue(const Task &task) {
@@ -84,6 +89,7 @@
         return;
     }
 
+    ALOGV("Adding task to the queue...");
     mQueue.push(task);
     mQueueCond.notify_one();
 }
diff --git a/services/core/jni/BroadcastRadio/Tuner.cpp b/services/core/jni/BroadcastRadio/Tuner.cpp
index 85603d5..e1ade4d 100644
--- a/services/core/jni/BroadcastRadio/Tuner.cpp
+++ b/services/core/jni/BroadcastRadio/Tuner.cpp
@@ -84,6 +84,7 @@
     bool mIsClosed = false;
     HalRevision mHalRev;
     bool mWithAudio;
+    bool mIsAudioConnected = false;
     Band mBand;
     wp<V1_0::IBroadcastRadio> mHalModule;
     wp<V1_1::IBroadcastRadio> mHalModule11;
@@ -142,6 +143,8 @@
 // TODO(b/62713378): implement support for multiple tuners open at the same time
 static void notifyAudioService(TunerContext& ctx, bool connected) {
     if (!ctx.mWithAudio) return;
+    if (ctx.mIsAudioConnected == connected) return;
+    ctx.mIsAudioConnected = connected;
 
     ALOGD("Notifying AudioService about new state: %d", connected);
     auto token = IPCThreadState::self()->clearCallingIdentity();
@@ -265,6 +268,14 @@
     return convert::BandConfigFromHal(env, halConfig, region).release();
 }
 
+static void nativeSetMuted(JNIEnv *env, jobject obj, jlong nativeContext, bool mute) {
+    ALOGV("%s(%d)", __func__, mute);
+    lock_guard<mutex> lk(gContextMutex);
+    auto& ctx = getNativeContext(nativeContext);
+
+    notifyAudioService(ctx, !mute);
+}
+
 static void nativeStep(JNIEnv *env, jobject obj, jlong nativeContext,
         bool directionDown, bool skipSubChannel) {
     ALOGV("%s", __func__);
@@ -497,6 +508,7 @@
             (void*)nativeSetConfiguration },
     { "nativeGetConfiguration", "(JI)Landroid/hardware/radio/RadioManager$BandConfig;",
             (void*)nativeGetConfiguration },
+    { "nativeSetMuted", "(JZ)V", (void*)nativeSetMuted },
     { "nativeStep", "(JZZ)V", (void*)nativeStep },
     { "nativeScan", "(JZZ)V", (void*)nativeScan },
     { "nativeTune", "(JLandroid/hardware/radio/ProgramSelector;)V", (void*)nativeTune },
diff --git a/services/core/jni/BroadcastRadio/regions.cpp b/services/core/jni/BroadcastRadio/regions.cpp
index e313521..b856419 100644
--- a/services/core/jni/BroadcastRadio/regions.cpp
+++ b/services/core/jni/BroadcastRadio/regions.cpp
@@ -64,7 +64,7 @@
     {
         { Region::ITU_2 },
         { Band::FM, Band::FM_HD },
-        87900,
+        87700,
         107900,
         200,
         Deemphasis::D75,
@@ -101,14 +101,14 @@
         { Region::ITU_1, Region::OIRT, Region::JAPAN, Region::KOREA },
         { Band::AM },
         153,
-        279,
+        282,
         9,
     },
     {  // AM MW
         { Region::ITU_1, Region::OIRT, Region::JAPAN, Region::KOREA },
         { Band::AM },
         531,
-        1611,
+        1620,
         9,
     },
     {  // AM SW
@@ -128,8 +128,8 @@
     {  // AM MW ITU2
         { Region::ITU_2 },
         { Band::AM, Band::AM_HD },
-        540,
-        1610,
+        530,
+        1700,
         10,
     },
     {  // AM SW ITU2
diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
index 2dc388a..ae7d6da 100644
--- a/services/core/jni/com_android_server_am_BatteryStatsService.cpp
+++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
@@ -63,6 +63,12 @@
 extern std::mutex gPowerHalMutex;
 extern bool getPowerHal();
 
+// Java methods used in getLowPowerStats
+static jmethodID jgetAndUpdatePlatformState = NULL;
+static jmethodID jgetSubsystem = NULL;
+static jmethodID jputVoter = NULL;
+static jmethodID jputState = NULL;
+
 static void wakeup_callback(bool success)
 {
     ALOGV("In wakeup_callback: %s", success ? "resumed from suspend" : "suspend aborted");
@@ -185,6 +191,97 @@
     return mergedreasonpos - mergedreason;
 }
 
+static void getLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject jrpmStats) {
+    if (jrpmStats == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException",
+                "The rpmstats jni input jobject jrpmStats is null.");
+        return;
+    }
+    if (jgetAndUpdatePlatformState == NULL || jgetSubsystem == NULL
+            || jputVoter == NULL || jputState == NULL) {
+        ALOGE("A rpmstats jni jmethodID is null.");
+        return;
+    }
+
+    std::lock_guard<std::mutex> lock(gPowerHalMutex);
+    if (!getPowerHal()) {
+        ALOGE("Power Hal not loaded");
+        return;
+    }
+
+    Return<void> ret = gPowerHalV1_0->getPlatformLowPowerStats(
+            [&env, &jrpmStats](hidl_vec<PowerStatePlatformSleepState> states, Status status) {
+
+            if (status != Status::SUCCESS) return;
+
+            for (size_t i = 0; i < states.size(); i++) {
+                const PowerStatePlatformSleepState& state = states[i];
+
+                jobject jplatformState = env->CallObjectMethod(jrpmStats,
+                        jgetAndUpdatePlatformState,
+                        env->NewStringUTF(state.name.c_str()),
+                        state.residencyInMsecSinceBoot,
+                        state.totalTransitions);
+                if (jplatformState == NULL) {
+                    ALOGE("The rpmstats jni jobject jplatformState is null.");
+                    return;
+                }
+
+                for (size_t j = 0; j < state.voters.size(); j++) {
+                    const PowerStateVoter& voter = state.voters[j];
+                    env->CallVoidMethod(jplatformState, jputVoter,
+                            env->NewStringUTF(voter.name.c_str()),
+                            voter.totalTimeInMsecVotedForSinceBoot,
+                            voter.totalNumberOfTimesVotedSinceBoot);
+                }
+            }
+    });
+    if (!ret.isOk()) {
+        ALOGE("getLowPowerStats() failed: power HAL service not available");
+        gPowerHalV1_0 = nullptr;
+        return;
+    }
+
+    //Trying to cast to IPower 1.1, this will succeed only for devices supporting 1.1
+    sp<android::hardware::power::V1_1::IPower> gPowerHal_1_1
+            = android::hardware::power::V1_1::IPower::castFrom(gPowerHalV1_0);
+    if (gPowerHal_1_1 == nullptr) {
+        //This device does not support IPower@1.1, exiting gracefully
+        return;
+    }
+    ret = gPowerHal_1_1->getSubsystemLowPowerStats(
+            [&env, &jrpmStats](hidl_vec<PowerStateSubsystem> subsystems, Status status) {
+
+        if (status != Status::SUCCESS) return;
+
+        if (subsystems.size() > 0) {
+            for (size_t i = 0; i < subsystems.size(); i++) {
+                const PowerStateSubsystem &subsystem = subsystems[i];
+
+                jobject jsubsystem = env->CallObjectMethod(jrpmStats, jgetSubsystem,
+                        env->NewStringUTF(subsystem.name.c_str()));
+                if (jsubsystem == NULL) {
+                    ALOGE("The rpmstats jni jobject jsubsystem is null.");
+                    return;
+                }
+
+                for (size_t j = 0; j < subsystem.states.size(); j++) {
+                    const PowerStateSubsystemSleepState& state = subsystem.states[j];
+                    env->CallVoidMethod(jsubsystem, jputState,
+                            env->NewStringUTF(state.name.c_str()),
+                            state.residencyInMsecSinceBoot,
+                            state.totalTransitions);
+                }
+            }
+        }
+    });
+    if (!ret.isOk()) {
+        ALOGE("getSubsystemLowPowerStats() failed: power HAL service not available");
+        gPowerHalV1_0 = nullptr;
+    }
+    // gPowerHalMutex released here
+}
+
 static jint getPlatformLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject outBuf) {
     char *output = (char*)env->GetDirectBufferAddress(outBuf);
     char *offset = output;
@@ -369,12 +466,33 @@
 
 static const JNINativeMethod method_table[] = {
     { "nativeWaitWakeup", "(Ljava/nio/ByteBuffer;)I", (void*)nativeWaitWakeup },
+    { "getLowPowerStats", "(Lcom/android/internal/os/RpmStats;)V", (void*)getLowPowerStats },
     { "getPlatformLowPowerStats", "(Ljava/nio/ByteBuffer;)I", (void*)getPlatformLowPowerStats },
     { "getSubsystemLowPowerStats", "(Ljava/nio/ByteBuffer;)I", (void*)getSubsystemLowPowerStats },
 };
 
 int register_android_server_BatteryStatsService(JNIEnv *env)
 {
+    // get java classes and methods
+    jclass clsRpmStats = env->FindClass("com/android/internal/os/RpmStats");
+    jclass clsPowerStatePlatformSleepState =
+            env->FindClass("com/android/internal/os/RpmStats$PowerStatePlatformSleepState");
+    jclass clsPowerStateSubsystem =
+            env->FindClass("com/android/internal/os/RpmStats$PowerStateSubsystem");
+    if (clsRpmStats == NULL || clsPowerStatePlatformSleepState == NULL
+            || clsPowerStateSubsystem == NULL) {
+        ALOGE("A rpmstats jni jclass is null.");
+    } else {
+        jgetAndUpdatePlatformState = env->GetMethodID(clsRpmStats, "getAndUpdatePlatformState",
+                "(Ljava/lang/String;JI)Lcom/android/internal/os/RpmStats$PowerStatePlatformSleepState;");
+        jgetSubsystem = env->GetMethodID(clsRpmStats, "getSubsystem",
+                "(Ljava/lang/String;)Lcom/android/internal/os/RpmStats$PowerStateSubsystem;");
+        jputVoter = env->GetMethodID(clsPowerStatePlatformSleepState, "putVoter",
+                "(Ljava/lang/String;JI)V");
+        jputState = env->GetMethodID(clsPowerStateSubsystem, "putState",
+                "(Ljava/lang/String;JI)V");
+    }
+
     return jniRegisterNativeMethods(env, "com/android/server/am/BatteryStatsService",
             method_table, NELEM(method_table));
 }
diff --git a/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp b/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
index f9cbd16..9a17635 100644
--- a/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
+++ b/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
@@ -113,7 +113,7 @@
     hidl_handle h1(handleFromFileDescriptor(std::move(fd1))),
                 h2(handleFromFileDescriptor(std::move(fd2)));
 
-    bool rval;
+    bool rval(false);
     hidl_string msg;
     const auto status = configInterface->setHandles(h1, h2,
             [&rval, &msg](bool success, const hidl_string& errMsg) {
@@ -123,6 +123,8 @@
     if (!status.isOk() || !rval) {
         ALOGE("IOffloadConfig::setHandles() error: '%s' / '%s'",
               status.description().c_str(), msg.c_str());
+        // If status is somehow not ok, make sure rval captures this too.
+        rval = false;
     }
 
     return rval;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 0b967b3..38d7d25 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -99,6 +99,7 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.ParceledListSlice;
+import android.content.pm.PermissionInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.StringParceledListSlice;
@@ -152,6 +153,7 @@
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.EventLog;
 import android.util.Log;
 import android.util.Pair;
 import android.util.Slog;
@@ -4106,6 +4108,16 @@
 
     private boolean isActivePasswordSufficientForUserLocked(
             DevicePolicyData policy, int userHandle, boolean parent) {
+        final int requiredPasswordQuality = getPasswordQuality(null, userHandle, parent);
+        if (requiredPasswordQuality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
+            // A special case is when there is no required password quality, then we just return
+            // true since any password would be sufficient. This is for the scenario when a work
+            // profile is first created so there is no information about the current password but
+            // it should be considered sufficient as there is no password requirement either.
+            // This is useful since it short-circuits the password checkpoint for FDE device below.
+            return true;
+        }
+
         if (!mInjector.storageManagerIsFileBasedEncryptionEnabled()
                 && !policy.mPasswordStateHasBeenSetSinceBoot) {
             // Before user enters their password for the first time after a reboot, return the
@@ -4116,7 +4128,6 @@
             return policy.mPasswordValidAtLastCheckpoint;
         }
 
-        final int requiredPasswordQuality = getPasswordQuality(null, userHandle, parent);
         if (policy.mActivePasswordMetrics.quality < requiredPasswordQuality) {
             return false;
         }
@@ -9581,6 +9592,10 @@
                         < android.os.Build.VERSION_CODES.M) {
                     return false;
                 }
+                if (!isRuntimePermission(permission)) {
+                    EventLog.writeEvent(0x534e4554, "62623498", user.getIdentifier(), "");
+                    return false;
+                }
                 final PackageManager packageManager = mInjector.getPackageManager();
                 switch (grantState) {
                     case DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED: {
@@ -9607,6 +9622,8 @@
                 return true;
             } catch (SecurityException se) {
                 return false;
+            } catch (NameNotFoundException e) {
+                return false;
             } finally {
                 mInjector.binderRestoreCallingIdentity(ident);
             }
@@ -9656,6 +9673,13 @@
         }
     }
 
+    public boolean isRuntimePermission(String permissionName) throws NameNotFoundException {
+        final PackageManager packageManager = mInjector.getPackageManager();
+        PermissionInfo permissionInfo = packageManager.getPermissionInfo(permissionName, 0);
+        return (permissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
+                == PermissionInfo.PROTECTION_DANGEROUS;
+    }
+
     @Override
     public boolean isProvisioningAllowed(String action, String packageName) {
         Preconditions.checkNotNull(packageName);
diff --git a/services/net/java/android/net/ip/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java
index 97c9d82..88bd78c 100644
--- a/services/net/java/android/net/ip/IpReachabilityMonitor.java
+++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java
@@ -183,44 +183,14 @@
         final byte[] msg = RtNetlinkNeighborMessage.newNewNeighborMessage(
                 1, ip, StructNdMsg.NUD_PROBE, ifIndex, null);
 
-        int errno = -OsConstants.EPROTO;
-        try (NetlinkSocket nlSocket = new NetlinkSocket(OsConstants.NETLINK_ROUTE)) {
-            final long IO_TIMEOUT = 300L;
-            nlSocket.connectToKernel();
-            nlSocket.sendMessage(msg, 0, msg.length, IO_TIMEOUT);
-            final ByteBuffer bytes = nlSocket.recvMessage(IO_TIMEOUT);
-            // recvMessage() guaranteed to not return null if it did not throw.
-            final NetlinkMessage response = NetlinkMessage.parse(bytes);
-            if (response != null && response instanceof NetlinkErrorMessage &&
-                    (((NetlinkErrorMessage) response).getNlMsgError() != null)) {
-                errno = ((NetlinkErrorMessage) response).getNlMsgError().error;
-                if (errno != 0) {
-                    // TODO: consider ignoring EINVAL (-22), which appears to be
-                    // normal when probing a neighbor for which the kernel does
-                    // not already have / no longer has a link layer address.
-                    Log.e(TAG, "Error " + msgSnippet + ", errmsg=" + response.toString());
-                }
-            } else {
-                String errmsg;
-                if (response == null) {
-                    bytes.position(0);
-                    errmsg = "raw bytes: " + NetlinkConstants.hexify(bytes);
-                } else {
-                    errmsg = response.toString();
-                }
-                Log.e(TAG, "Error " + msgSnippet + ", errmsg=" + errmsg);
-            }
+        try {
+            NetlinkSocket.sendOneShotKernelMessage(OsConstants.NETLINK_ROUTE, msg);
         } catch (ErrnoException e) {
-            Log.e(TAG, "Error " + msgSnippet, e);
-            errno = -e.errno;
-        } catch (InterruptedIOException e) {
-            Log.e(TAG, "Error " + msgSnippet, e);
-            errno = -OsConstants.ETIMEDOUT;
-        } catch (SocketException e) {
-            Log.e(TAG, "Error " + msgSnippet, e);
-            errno = -OsConstants.EIO;
+            Log.e(TAG, "Error " + msgSnippet + ": " + e);
+            return -e.errno;
         }
-        return errno;
+
+        return 0;
     }
 
     public IpReachabilityMonitor(Context context, String ifName, SharedLog log, Callback callback) {
diff --git a/services/net/java/android/net/netlink/ConntrackMessage.java b/services/net/java/android/net/netlink/ConntrackMessage.java
new file mode 100644
index 0000000..605c46b
--- /dev/null
+++ b/services/net/java/android/net/netlink/ConntrackMessage.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2017 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.net.netlink;
+
+import static android.net.netlink.NetlinkConstants.alignedLengthOf;
+import static android.net.netlink.StructNlAttr.makeNestedType;
+import static android.net.netlink.StructNlAttr.NLA_HEADERLEN;
+import static android.net.netlink.StructNlMsgHdr.NLM_F_ACK;
+import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP;
+import static android.net.netlink.StructNlMsgHdr.NLM_F_REPLACE;
+import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST;
+import static android.net.util.NetworkConstants.IPV4_ADDR_LEN;
+import static java.nio.ByteOrder.BIG_ENDIAN;
+
+import android.system.OsConstants;
+import android.util.Log;
+import libcore.io.SizeOf;
+
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+
+/**
+ * A NetlinkMessage subclass for netlink conntrack messages.
+ *
+ * see also: &lt;linux_src&gt;/include/uapi/linux/netfilter/nfnetlink_conntrack.h
+ *
+ * @hide
+ */
+public class ConntrackMessage extends NetlinkMessage {
+    public static final int STRUCT_SIZE = StructNlMsgHdr.STRUCT_SIZE + StructNfGenMsg.STRUCT_SIZE;
+
+    public static final short NFNL_SUBSYS_CTNETLINK = 1;
+    public static final short IPCTNL_MSG_CT_NEW = 0;
+
+    // enum ctattr_type
+    public static final short CTA_TUPLE_ORIG  = 1;
+    public static final short CTA_TUPLE_REPLY = 2;
+    public static final short CTA_TIMEOUT     = 7;
+
+    // enum ctattr_tuple
+    public static final short CTA_TUPLE_IP    = 1;
+    public static final short CTA_TUPLE_PROTO = 2;
+
+    // enum ctattr_ip
+    public static final short CTA_IP_V4_SRC = 1;
+    public static final short CTA_IP_V4_DST = 2;
+
+    // enum ctattr_l4proto
+    public static final short CTA_PROTO_NUM      = 1;
+    public static final short CTA_PROTO_SRC_PORT = 2;
+    public static final short CTA_PROTO_DST_PORT = 3;
+
+    public static byte[] newIPv4TimeoutUpdateRequest(
+            int proto, Inet4Address src, int sport, Inet4Address dst, int dport, int timeoutSec) {
+        // *** STYLE WARNING ***
+        //
+        // Code below this point uses extra block indentation to highlight the
+        // packing of nested tuple netlink attribute types.
+        final StructNlAttr ctaTupleOrig = new StructNlAttr(CTA_TUPLE_ORIG,
+                new StructNlAttr(CTA_TUPLE_IP,
+                        new StructNlAttr(CTA_IP_V4_SRC, src),
+                        new StructNlAttr(CTA_IP_V4_DST, dst)),
+                new StructNlAttr(CTA_TUPLE_PROTO,
+                        new StructNlAttr(CTA_PROTO_NUM, (byte) proto),
+                        new StructNlAttr(CTA_PROTO_SRC_PORT, (short) sport, BIG_ENDIAN),
+                        new StructNlAttr(CTA_PROTO_DST_PORT, (short) dport, BIG_ENDIAN)));
+
+        final StructNlAttr ctaTimeout = new StructNlAttr(CTA_TIMEOUT, timeoutSec, BIG_ENDIAN);
+
+        final int payloadLength = ctaTupleOrig.getAlignedLength() + ctaTimeout.getAlignedLength();
+        final byte[] bytes = new byte[STRUCT_SIZE + payloadLength];
+        final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
+        byteBuffer.order(ByteOrder.nativeOrder());
+
+        final ConntrackMessage ctmsg = new ConntrackMessage();
+        ctmsg.mHeader.nlmsg_len = bytes.length;
+        ctmsg.mHeader.nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_NEW;
+        ctmsg.mHeader.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE;
+        ctmsg.mHeader.nlmsg_seq = 1;
+        ctmsg.pack(byteBuffer);
+
+        ctaTupleOrig.pack(byteBuffer);
+        ctaTimeout.pack(byteBuffer);
+
+        return bytes;
+    }
+
+    protected StructNfGenMsg mNfGenMsg;
+
+    private ConntrackMessage() {
+        super(new StructNlMsgHdr());
+        mNfGenMsg = new StructNfGenMsg((byte) OsConstants.AF_INET);
+    }
+
+    public void pack(ByteBuffer byteBuffer) {
+        mHeader.pack(byteBuffer);
+        mNfGenMsg.pack(byteBuffer);
+    }
+}
diff --git a/services/net/java/android/net/netlink/NetlinkSocket.java b/services/net/java/android/net/netlink/NetlinkSocket.java
index 657d48c..a9e0cd9 100644
--- a/services/net/java/android/net/netlink/NetlinkSocket.java
+++ b/services/net/java/android/net/netlink/NetlinkSocket.java
@@ -51,6 +51,47 @@
     private long mLastRecvTimeoutMs;
     private long mLastSendTimeoutMs;
 
+    public static void sendOneShotKernelMessage(int nlProto, byte[] msg) throws ErrnoException {
+        final String errPrefix = "Error in NetlinkSocket.sendOneShotKernelMessage";
+
+        try (NetlinkSocket nlSocket = new NetlinkSocket(nlProto)) {
+            final long IO_TIMEOUT = 300L;
+            nlSocket.connectToKernel();
+            nlSocket.sendMessage(msg, 0, msg.length, IO_TIMEOUT);
+            final ByteBuffer bytes = nlSocket.recvMessage(IO_TIMEOUT);
+            // recvMessage() guaranteed to not return null if it did not throw.
+            final NetlinkMessage response = NetlinkMessage.parse(bytes);
+            if (response != null && response instanceof NetlinkErrorMessage &&
+                    (((NetlinkErrorMessage) response).getNlMsgError() != null)) {
+                final int errno = ((NetlinkErrorMessage) response).getNlMsgError().error;
+                if (errno != 0) {
+                    // TODO: consider ignoring EINVAL (-22), which appears to be
+                    // normal when probing a neighbor for which the kernel does
+                    // not already have / no longer has a link layer address.
+                    Log.e(TAG, errPrefix + ", errmsg=" + response.toString());
+                    // Note: convert kernel errnos (negative) into userspace errnos (positive).
+                    throw new ErrnoException(response.toString(), Math.abs(errno));
+                }
+            } else {
+                final String errmsg;
+                if (response == null) {
+                    bytes.position(0);
+                    errmsg = "raw bytes: " + NetlinkConstants.hexify(bytes);
+                } else {
+                    errmsg = response.toString();
+                }
+                Log.e(TAG, errPrefix + ", errmsg=" + errmsg);
+                throw new ErrnoException(errmsg, OsConstants.EPROTO);
+            }
+        } catch (InterruptedIOException e) {
+            Log.e(TAG, errPrefix, e);
+            throw new ErrnoException(errPrefix, OsConstants.ETIMEDOUT, e);
+        } catch (SocketException e) {
+            Log.e(TAG, errPrefix, e);
+            throw new ErrnoException(errPrefix, OsConstants.EIO, e);
+        }
+    }
+
     public NetlinkSocket(int nlProto) throws ErrnoException {
         mDescriptor = Os.socket(
                 OsConstants.AF_NETLINK, OsConstants.SOCK_DGRAM, nlProto);
diff --git a/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java b/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java
index 02df131..e784fbb 100644
--- a/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java
+++ b/services/net/java/android/net/netlink/RtNetlinkNeighborMessage.java
@@ -36,7 +36,7 @@
 
 
 /**
- * A NetlinkMessage subclass for netlink error messages.
+ * A NetlinkMessage subclass for rtnetlink neighbor messages.
  *
  * see also: &lt;linux_src&gt;/include/uapi/linux/neighbour.h
  *
diff --git a/services/net/java/android/net/netlink/StructNfGenMsg.java b/services/net/java/android/net/netlink/StructNfGenMsg.java
new file mode 100644
index 0000000..99695e2
--- /dev/null
+++ b/services/net/java/android/net/netlink/StructNfGenMsg.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 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.net.netlink;
+
+import libcore.io.SizeOf;
+
+import java.nio.ByteBuffer;
+
+
+/**
+ * struct nfgenmsg
+ *
+ * see &lt;linux_src&gt;/include/uapi/linux/netfilter/nfnetlink.h
+ *
+ * @hide
+ */
+public class StructNfGenMsg {
+    public static final int STRUCT_SIZE = 2 + SizeOf.SHORT;
+
+    public static final int NFNETLINK_V0 = 0;
+
+    final public byte nfgen_family;
+    final public byte version;
+    final public short res_id;  // N.B.: this is big endian in the kernel
+
+    public StructNfGenMsg(byte family) {
+        nfgen_family = family;
+        version = (byte) NFNETLINK_V0;
+        res_id = (short) 0;
+    }
+
+    public void pack(ByteBuffer byteBuffer) {
+        byteBuffer.put(nfgen_family);
+        byteBuffer.put(version);
+        byteBuffer.putShort(res_id);
+    }
+}
diff --git a/services/net/java/android/net/netlink/StructNlAttr.java b/services/net/java/android/net/netlink/StructNlAttr.java
index 597a6aa..811bdbb 100644
--- a/services/net/java/android/net/netlink/StructNlAttr.java
+++ b/services/net/java/android/net/netlink/StructNlAttr.java
@@ -34,7 +34,12 @@
  */
 public class StructNlAttr {
     // Already aligned.
-    public static final int NLA_HEADERLEN         = 4;
+    public static final int NLA_HEADERLEN  = 4;
+    public static final int NLA_F_NESTED   = (1 << 15);
+
+    public static short makeNestedType(short type) {
+        return (short) (type | NLA_F_NESTED);
+    }
 
     // Return a (length, type) object only, without consuming any bytes in
     // |byteBuffer| and without copying or interpreting any value bytes.
@@ -46,10 +51,17 @@
         }
         final int baseOffset = byteBuffer.position();
 
-        final StructNlAttr struct = new StructNlAttr();
-        struct.nla_len = byteBuffer.getShort();
-        struct.nla_type = byteBuffer.getShort();
-        struct.mByteOrder = byteBuffer.order();
+        // Assume the byte order of the buffer is the expected byte order of the value.
+        final StructNlAttr struct = new StructNlAttr(byteBuffer.order());
+        // The byte order of nla_len and nla_type is always native.
+        final ByteOrder originalOrder = byteBuffer.order();
+        byteBuffer.order(ByteOrder.nativeOrder());
+        try {
+            struct.nla_len = byteBuffer.getShort();
+            struct.nla_type = byteBuffer.getShort();
+        } finally {
+            byteBuffer.order(originalOrder);
+        }
 
         byteBuffer.position(baseOffset);
         if (struct.nla_len < NLA_HEADERLEN) {
@@ -78,13 +90,65 @@
         return struct;
     }
 
-    public short nla_len;
+    public short nla_len = (short) NLA_HEADERLEN;
     public short nla_type;
     public byte[] nla_value;
-    public ByteOrder mByteOrder;
 
-    public StructNlAttr() {
-        mByteOrder = ByteOrder.nativeOrder();
+    // The byte order used to read/write the value member. Netlink length and
+    // type members are always read/written in native order.
+    private ByteOrder mByteOrder = ByteOrder.nativeOrder();
+
+    public StructNlAttr() {}
+
+    public StructNlAttr(ByteOrder byteOrder) {
+        mByteOrder = byteOrder;
+    }
+
+    public StructNlAttr(short type, byte value) {
+        nla_type = type;
+        setValue(new byte[1]);
+        nla_value[0] = value;
+    }
+
+    public StructNlAttr(short type, short value) {
+        this(type, value, ByteOrder.nativeOrder());
+    }
+
+    public StructNlAttr(short type, short value, ByteOrder order) {
+        this(order);
+        nla_type = type;
+        setValue(new byte[SizeOf.SHORT]);
+        getValueAsByteBuffer().putShort(value);
+    }
+
+    public StructNlAttr(short type, int value) {
+        this(type, value, ByteOrder.nativeOrder());
+    }
+
+    public StructNlAttr(short type, int value, ByteOrder order) {
+        this(order);
+        nla_type = type;
+        setValue(new byte[SizeOf.INT]);
+        getValueAsByteBuffer().putInt(value);
+    }
+
+    public StructNlAttr(short type, InetAddress ip) {
+        nla_type = type;
+        setValue(ip.getAddress());
+    }
+
+    public StructNlAttr(short type, StructNlAttr... nested) {
+        this();
+        nla_type = makeNestedType(type);
+
+        int payloadLength = 0;
+        for (StructNlAttr nla : nested) payloadLength += nla.getAlignedLength();
+        setValue(new byte[payloadLength]);
+
+        final ByteBuffer buf = getValueAsByteBuffer();
+        for (StructNlAttr nla : nested) {
+            nla.pack(buf);
+        }
     }
 
     public int getAlignedLength() {
@@ -117,13 +181,25 @@
     }
 
     public void pack(ByteBuffer byteBuffer) {
+        final ByteOrder originalOrder = byteBuffer.order();
         final int originalPosition = byteBuffer.position();
-        byteBuffer.putShort(nla_len);
-        byteBuffer.putShort(nla_type);
-        byteBuffer.put(nla_value);
+
+        byteBuffer.order(ByteOrder.nativeOrder());
+        try {
+            byteBuffer.putShort(nla_len);
+            byteBuffer.putShort(nla_type);
+            if (nla_value != null) byteBuffer.put(nla_value);
+        } finally {
+            byteBuffer.order(originalOrder);
+        }
         byteBuffer.position(originalPosition + getAlignedLength());
     }
 
+    private void setValue(byte[] value) {
+        nla_value = value;
+        nla_len = (short) (NLA_HEADERLEN + ((nla_value != null) ? nla_value.length : 0));
+    }
+
     @Override
     public String toString() {
         return "StructNlAttr{ "
diff --git a/services/tests/notification/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/notification/src/com/android/server/notification/ManagedServicesTest.java
index 613f01c..a4b9b25 100644
--- a/services/tests/notification/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/notification/src/com/android/server/notification/ManagedServicesTest.java
@@ -254,6 +254,14 @@
             loadXml(service);
 
             verifyExpectedApprovedEntries(service);
+
+            int[] invalidUsers = new int[] {98, 99};
+            for (int invalidUser : invalidUsers) {
+                assertFalse("service type " + service.mApprovalLevel + ":"
+                                + invalidUser + " is allowed for user " + invalidUser,
+                        service.isPackageOrComponentAllowed(
+                                String.valueOf(invalidUser), invalidUser));
+            }
         }
     }
 
@@ -616,6 +624,14 @@
             xml.append(getXmlEntry(
                     mExpectedSecondary.get(service.mApprovalLevel).get(userId), userId, false));
         }
+        xml.append("<" + ManagedServices.TAG_MANAGED_SERVICES + " "
+                        + ManagedServices.ATT_USER_ID + "=\"99\" "
+                        + ManagedServices.ATT_IS_PRIMARY + "=\"true\" "
+                        + ManagedServices.ATT_APPROVED_LIST + "=\"99\" />\n");
+        xml.append("<" + ManagedServices.TAG_MANAGED_SERVICES + " "
+                + ManagedServices.ATT_USER_ID + "=\"98\" "
+                + ManagedServices.ATT_IS_PRIMARY + "=\"false\" "
+                + ManagedServices.ATT_APPROVED_LIST + "=\"98\" />\n");
         xml.append("</" + service.getConfig().xmlTag + ">");
 
         XmlPullParser parser = Xml.newPullParser();
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index 2252c85..e51f7a9 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -20,15 +20,19 @@
 import static android.view.WindowManagerPolicy.NAV_BAR_LEFT;
 import static android.view.WindowManagerPolicy.NAV_BAR_RIGHT;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.when;
 
 import android.content.ComponentName;
+import android.content.pm.ActivityInfo;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.MediumTest;
 import android.support.test.runner.AndroidJUnit4;
 
+import android.view.Display;
 import org.junit.runner.RunWith;
 import org.junit.Test;
 
@@ -46,6 +50,8 @@
 
     private final ComponentName testActivityComponent =
             ComponentName.unflattenFromString("com.foo/.BarActivity");
+    private final ComponentName secondaryActivityComponent =
+            ComponentName.unflattenFromString("com.foo/.BarActivity2");
     @Test
     public void testStackCleanupOnClearingTask() throws Exception {
         final ActivityManagerService service = createActivityManagerService();
@@ -131,4 +137,45 @@
         record.ensureActivityConfigurationLocked(0 /* globalChanges */, false /* preserveWindow */);
         assertEquals(expectedActivityBounds, record.getBounds());
     }
+
+
+    @Test
+    public void testCanBeLaunchedOnDisplay() throws Exception {
+        testSupportsLaunchingResizeable(false /*taskPresent*/, true /*taskResizeable*/,
+                true /*activityResizeable*/, true /*expected*/);
+
+        testSupportsLaunchingResizeable(false /*taskPresent*/, true /*taskResizeable*/,
+                false /*activityResizeable*/, false /*expected*/);
+
+        testSupportsLaunchingResizeable(true /*taskPresent*/, false /*taskResizeable*/,
+                true /*activityResizeable*/, false /*expected*/);
+
+        testSupportsLaunchingResizeable(true /*taskPresent*/, true /*taskResizeable*/,
+                false /*activityResizeable*/, true /*expected*/);
+    }
+
+    private void testSupportsLaunchingResizeable(boolean taskPresent, boolean taskResizeable,
+            boolean activityResizeable, boolean expected) {
+        final ActivityManagerService service = createActivityManagerService();
+        service.mSupportsMultiWindow = true;
+
+
+        final TaskRecord task = taskPresent
+                ? createTask(service, testActivityComponent, TEST_STACK_ID) : null;
+
+        if (task != null) {
+            task.setResizeMode(taskResizeable ? ActivityInfo.RESIZE_MODE_RESIZEABLE
+                    : ActivityInfo.RESIZE_MODE_UNRESIZEABLE);
+        }
+
+        final ActivityRecord record = createActivity(service, secondaryActivityComponent,
+                task);
+        record.info.resizeMode = activityResizeable ? ActivityInfo.RESIZE_MODE_RESIZEABLE
+                : ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+
+        record.canBeLaunchedOnDisplay(Display.DEFAULT_DISPLAY);
+
+        assertEquals(((TestActivityStackSupervisor) service.mStackSupervisor)
+                .getLastResizeableFromCanPlaceEntityOnDisplay(), expected);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index a6c0cf1..04ddae9 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -163,6 +163,7 @@
      */
     protected static class TestActivityStackSupervisor extends ActivityStackSupervisor {
         private final ActivityDisplay mDisplay;
+        private boolean mLastResizeable;
 
         public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
             super(service, looper);
@@ -170,6 +171,22 @@
             mDisplay = new ActivityDisplay();
         }
 
+        // TODO: Use Mockito spy instead. Currently not possible due to TestActivityStackSupervisor
+        // access to ActivityDisplay
+        @Override
+        boolean canPlaceEntityOnDisplay(int displayId, boolean resizeable, int callingPid,
+                int callingUid, ActivityInfo activityInfo) {
+            mLastResizeable = resizeable;
+            return super.canPlaceEntityOnDisplay(displayId, resizeable, callingPid, callingUid,
+                    activityInfo);
+        }
+
+        // TODO: remove and use Mockito verify once {@link #canPlaceEntityOnDisplay} override is
+        // removed.
+        public boolean getLastResizeableFromCanPlaceEntityOnDisplay() {
+            return mLastResizeable;
+        }
+
         // No home stack is set.
         @Override
         void moveHomeStackToFront(String reason) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
index 9f77297..d136614 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -55,11 +55,11 @@
     public void testWriteReadApplicationRestrictions() throws IOException {
         AtomicFile atomicFile = new AtomicFile(restrictionsFile);
         Bundle bundle = createBundle();
-        UserManagerService.writeApplicationRestrictionsLP(bundle, atomicFile);
+        UserManagerService.writeApplicationRestrictionsLAr(bundle, atomicFile);
         assertTrue(atomicFile.getBaseFile().exists());
         String s = FileUtils.readTextFile(restrictionsFile, 10000, "");
         System.out.println("restrictionsFile: " + s);
-        bundle = UserManagerService.readApplicationRestrictionsLP(atomicFile);
+        bundle = UserManagerService.readApplicationRestrictionsLAr(atomicFile);
         System.out.println("readApplicationRestrictionsLocked bundle: " + bundle);
         assertBundle(bundle);
     }
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
index 2c56a82..150f7f0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
@@ -16,10 +16,14 @@
 
 package com.android.server.pm.dex;
 
+import com.android.server.pm.PackageDexOptimizer;
+
+import static com.android.server.pm.PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import android.content.pm.ApplicationInfo;
 import android.support.test.filters.SmallTest;
@@ -46,22 +50,35 @@
     private static final String DELEGATE_LAST_CLASS_LOADER_NAME =
             DelegateLastClassLoader.class.getName();
 
-    private ApplicationInfo createMockApplicationInfo(String baseClassLoader, boolean addSplits,
+    private static class TestData {
+        ApplicationInfo info;
+        boolean[] pathsWithCode;
+    }
+
+    private TestData createMockApplicationInfo(String baseClassLoader, boolean addSplits,
             boolean addSplitDependencies) {
         ApplicationInfo ai = new ApplicationInfo();
         String codeDir = "/data/app/mock.android.com";
         ai.setBaseCodePath(codeDir + "/base.dex");
         ai.classLoaderName = baseClassLoader;
         ai.privateFlags = ai.privateFlags | ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
+        boolean[] pathsWithCode;
+        if (!addSplits) {
+            pathsWithCode = new boolean[] {true};
+        } else {
+            pathsWithCode = new boolean[9];
+            Arrays.fill(pathsWithCode, true);
+            pathsWithCode[7] = false;  // config split
 
-        if (addSplits) {
             ai.setSplitCodePaths(new String[]{
                     codeDir + "/base-1.dex",
                     codeDir + "/base-2.dex",
                     codeDir + "/base-3.dex",
                     codeDir + "/base-4.dex",
                     codeDir + "/base-5.dex",
-                    codeDir + "/base-6.dex"});
+                    codeDir + "/base-6.dex",
+                    codeDir + "/config-split-7.dex",
+                    codeDir + "/feature-no-deps.dex"});
 
             ai.splitClassLoaderNames = new String[]{
                     DELEGATE_LAST_CLASS_LOADER_NAME,
@@ -69,7 +86,9 @@
                     PATH_CLASS_LOADER_NAME,
                     DEX_CLASS_LOADER_NAME,
                     PATH_CLASS_LOADER_NAME,
-                    null};  // A null class loader name should default to PathClassLoader.
+                    null,   // A null class loader name should default to PathClassLoader.
+                    null,   // The config split gets a null class loader.
+                    null};  // The feature split with no dependency and no specified class loader.
             if (addSplitDependencies) {
                 ai.splitDependencies = new SparseArray<>(ai.splitClassLoaderNames.length + 1);
                 ai.splitDependencies.put(0, new int[] {-1}); // base has no dependency
@@ -79,18 +98,24 @@
                 ai.splitDependencies.put(4, new int[] {0}); // split 4 depends on base
                 ai.splitDependencies.put(5, new int[] {0}); // split 5 depends on base
                 ai.splitDependencies.put(6, new int[] {5}); // split 6 depends on 5
+                // Do not add the config split to the dependency list.
+                // Do not add the feature split with no dependency to the dependency list.
             }
         }
-        return ai;
+        TestData data = new TestData();
+        data.info = ai;
+        data.pathsWithCode = pathsWithCode;
+        return data;
     }
 
     @Test
     public void testSplitChain() {
-        ApplicationInfo ai = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, true, true);
+        TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, true, true);
         String[] sharedLibrary = new String[] {"a.dex", "b.dex"};
-        String[] contexts = DexoptUtils.getClassLoaderContexts(ai, sharedLibrary);
+        String[] contexts = DexoptUtils.getClassLoaderContexts(
+                data.info, sharedLibrary, data.pathsWithCode);
 
-        assertEquals(7, contexts.length);
+        assertEquals(9, contexts.length);
         assertEquals("PCL[a.dex:b.dex]", contexts[0]);
         assertEquals("DLC[];DLC[base-2.dex];PCL[base-4.dex];PCL[a.dex:b.dex:base.dex]",
                 contexts[1]);
@@ -99,15 +124,18 @@
         assertEquals("PCL[];PCL[a.dex:b.dex:base.dex]", contexts[4]);
         assertEquals("PCL[];PCL[a.dex:b.dex:base.dex]", contexts[5]);
         assertEquals("PCL[];PCL[base-5.dex];PCL[a.dex:b.dex:base.dex]", contexts[6]);
+        assertEquals(null, contexts[7]);  // config split
+        assertEquals("PCL[]", contexts[8]);  // feature split with no dependency
     }
 
     @Test
     public void testSplitChainNoSplitDependencies() {
-        ApplicationInfo ai = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, true, false);
+        TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, true, false);
         String[] sharedLibrary = new String[] {"a.dex", "b.dex"};
-        String[] contexts = DexoptUtils.getClassLoaderContexts(ai, sharedLibrary);
+        String[] contexts = DexoptUtils.getClassLoaderContexts(
+                data.info, sharedLibrary, data.pathsWithCode);
 
-        assertEquals(7, contexts.length);
+        assertEquals(9, contexts.length);
         assertEquals("PCL[a.dex:b.dex]", contexts[0]);
         assertEquals("PCL[a.dex:b.dex:base.dex]", contexts[1]);
         assertEquals("PCL[a.dex:b.dex:base.dex:base-1.dex]", contexts[2]);
@@ -119,15 +147,21 @@
         assertEquals(
                 "PCL[a.dex:b.dex:base.dex:base-1.dex:base-2.dex:base-3.dex:base-4.dex:base-5.dex]",
                 contexts[6]);
+        assertEquals(null, contexts[7]);  // config split
+        assertEquals(
+                "PCL[a.dex:b.dex:base.dex:base-1.dex:base-2.dex:base-3.dex:base-4.dex:base-5.dex:base-6.dex:config-split-7.dex]",
+                contexts[8]);  // feature split with no dependency
     }
 
     @Test
     public void testSplitChainNoIsolationNoSharedLibrary() {
-        ApplicationInfo ai = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, true, true);
-        ai.privateFlags = ai.privateFlags & (~ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING);
-        String[] contexts = DexoptUtils.getClassLoaderContexts(ai, null);
+        TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, true, true);
+        data.info.privateFlags = data.info.privateFlags
+                & (~ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING);
+        String[] contexts = DexoptUtils.getClassLoaderContexts(
+                data.info, null, data.pathsWithCode);
 
-        assertEquals(7, contexts.length);
+        assertEquals(9, contexts.length);
         assertEquals("PCL[]", contexts[0]);
         assertEquals("PCL[base.dex]", contexts[1]);
         assertEquals("PCL[base.dex:base-1.dex]", contexts[2]);
@@ -137,14 +171,20 @@
         assertEquals(
                 "PCL[base.dex:base-1.dex:base-2.dex:base-3.dex:base-4.dex:base-5.dex]",
                 contexts[6]);
+        assertEquals(null, contexts[7]);  // config split
+        assertEquals(
+                "PCL[base.dex:base-1.dex:base-2.dex:base-3.dex:base-4.dex:base-5.dex:base-6.dex:config-split-7.dex]",
+                contexts[8]);  // feature split with no dependency
     }
+
     @Test
     public void testSplitChainNoSharedLibraries() {
-        ApplicationInfo ai = createMockApplicationInfo(
+        TestData data = createMockApplicationInfo(
                 DELEGATE_LAST_CLASS_LOADER_NAME, true, true);
-        String[] contexts = DexoptUtils.getClassLoaderContexts(ai, null);
+        String[] contexts = DexoptUtils.getClassLoaderContexts(
+                data.info, null, data.pathsWithCode);
 
-        assertEquals(7, contexts.length);
+        assertEquals(9, contexts.length);
         assertEquals("DLC[]", contexts[0]);
         assertEquals("DLC[];DLC[base-2.dex];PCL[base-4.dex];DLC[base.dex]", contexts[1]);
         assertEquals("DLC[];PCL[base-4.dex];DLC[base.dex]", contexts[2]);
@@ -152,16 +192,19 @@
         assertEquals("PCL[];DLC[base.dex]", contexts[4]);
         assertEquals("PCL[];DLC[base.dex]", contexts[5]);
         assertEquals("PCL[];PCL[base-5.dex];DLC[base.dex]", contexts[6]);
+        assertEquals(null, contexts[7]);  // config split
+        assertEquals("PCL[]", contexts[8]);  // feature split with no dependency
     }
 
     @Test
     public void testSplitChainWithNullPrimaryClassLoader() {
         // A null classLoaderName should mean PathClassLoader.
-        ApplicationInfo ai = createMockApplicationInfo(null, true, true);
+        TestData data = createMockApplicationInfo(null, true, true);
         String[] sharedLibrary = new String[] {"a.dex", "b.dex"};
-        String[] contexts = DexoptUtils.getClassLoaderContexts(ai, sharedLibrary);
+        String[] contexts = DexoptUtils.getClassLoaderContexts(
+                data.info, sharedLibrary, data.pathsWithCode);
 
-        assertEquals(7, contexts.length);
+        assertEquals(9, contexts.length);
         assertEquals("PCL[a.dex:b.dex]", contexts[0]);
         assertEquals("DLC[];DLC[base-2.dex];PCL[base-4.dex];PCL[a.dex:b.dex:base.dex]", contexts[1]);
         assertEquals("DLC[];PCL[base-4.dex];PCL[a.dex:b.dex:base.dex]", contexts[2]);
@@ -169,13 +212,16 @@
         assertEquals("PCL[];PCL[a.dex:b.dex:base.dex]", contexts[4]);
         assertEquals("PCL[];PCL[a.dex:b.dex:base.dex]", contexts[5]);
         assertEquals("PCL[];PCL[base-5.dex];PCL[a.dex:b.dex:base.dex]", contexts[6]);
+        assertEquals(null, contexts[7]);  // config split
+        assertEquals("PCL[]", contexts[8]);  // feature split with no dependency
     }
 
     @Test
     public void tesNoSplits() {
-        ApplicationInfo ai = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, false, false);
+        TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, false, false);
         String[] sharedLibrary = new String[] {"a.dex", "b.dex"};
-        String[] contexts = DexoptUtils.getClassLoaderContexts(ai, sharedLibrary);
+        String[] contexts = DexoptUtils.getClassLoaderContexts(
+                data.info, sharedLibrary, data.pathsWithCode);
 
         assertEquals(1, contexts.length);
         assertEquals("PCL[a.dex:b.dex]", contexts[0]);
@@ -183,9 +229,10 @@
 
     @Test
     public void tesNoSplitsNullClassLoaderName() {
-        ApplicationInfo ai = createMockApplicationInfo(null, false, false);
+        TestData data = createMockApplicationInfo(null, false, false);
         String[] sharedLibrary = new String[] {"a.dex", "b.dex"};
-        String[] contexts = DexoptUtils.getClassLoaderContexts(ai, sharedLibrary);
+        String[] contexts = DexoptUtils.getClassLoaderContexts(
+                data.info, sharedLibrary, data.pathsWithCode);
 
         assertEquals(1, contexts.length);
         assertEquals("PCL[a.dex:b.dex]", contexts[0]);
@@ -193,10 +240,11 @@
 
     @Test
     public void tesNoSplitDelegateLast() {
-        ApplicationInfo ai = createMockApplicationInfo(
+        TestData data = createMockApplicationInfo(
                 DELEGATE_LAST_CLASS_LOADER_NAME, false, false);
         String[] sharedLibrary = new String[] {"a.dex", "b.dex"};
-        String[] contexts = DexoptUtils.getClassLoaderContexts(ai, sharedLibrary);
+        String[] contexts = DexoptUtils.getClassLoaderContexts(
+                data.info, sharedLibrary, data.pathsWithCode);
 
         assertEquals(1, contexts.length);
         assertEquals("DLC[a.dex:b.dex]", contexts[0]);
@@ -204,8 +252,9 @@
 
     @Test
     public void tesNoSplitsNoSharedLibraries() {
-        ApplicationInfo ai = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, false, false);
-        String[] contexts = DexoptUtils.getClassLoaderContexts(ai, null);
+        TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, false, false);
+        String[] contexts = DexoptUtils.getClassLoaderContexts(
+                data.info, null, data.pathsWithCode);
 
         assertEquals(1, contexts.length);
         assertEquals("PCL[]", contexts[0]);
@@ -213,15 +262,55 @@
 
     @Test
     public void tesNoSplitDelegateLastNoSharedLibraries() {
-        ApplicationInfo ai = createMockApplicationInfo(
+        TestData data = createMockApplicationInfo(
                 DELEGATE_LAST_CLASS_LOADER_NAME, false, false);
-        String[] contexts = DexoptUtils.getClassLoaderContexts(ai, null);
+        String[] contexts = DexoptUtils.getClassLoaderContexts(
+                data.info, null, data.pathsWithCode);
 
         assertEquals(1, contexts.length);
         assertEquals("DLC[]", contexts[0]);
     }
 
     @Test
+    public void testContextWithNoCode() {
+        TestData data = createMockApplicationInfo(null, true, false);
+        Arrays.fill(data.pathsWithCode, false);
+
+        String[] sharedLibrary = new String[] {"a.dex", "b.dex"};
+        String[] contexts = DexoptUtils.getClassLoaderContexts(
+                data.info, sharedLibrary, data.pathsWithCode);
+
+        assertEquals(9, contexts.length);
+        assertEquals(null, contexts[0]);
+        assertEquals(null, contexts[1]);
+        assertEquals(null, contexts[2]);
+        assertEquals(null, contexts[3]);
+        assertEquals(null, contexts[4]);
+        assertEquals(null, contexts[5]);
+        assertEquals(null, contexts[6]);
+        assertEquals(null, contexts[7]);
+    }
+
+    @Test
+    public void testContextBaseNoCode() {
+        TestData data = createMockApplicationInfo(null, true, true);
+        data.pathsWithCode[0] = false;
+        String[] sharedLibrary = new String[] {"a.dex", "b.dex"};
+        String[] contexts = DexoptUtils.getClassLoaderContexts(
+                data.info, sharedLibrary, data.pathsWithCode);
+
+        assertEquals(9, contexts.length);
+        assertEquals(null, contexts[0]);
+        assertEquals("DLC[];DLC[base-2.dex];PCL[base-4.dex];PCL[a.dex:b.dex:base.dex]", contexts[1]);
+        assertEquals("DLC[];PCL[base-4.dex];PCL[a.dex:b.dex:base.dex]", contexts[2]);
+        assertEquals("PCL[];PCL[base-4.dex];PCL[a.dex:b.dex:base.dex]", contexts[3]);
+        assertEquals("PCL[];PCL[a.dex:b.dex:base.dex]", contexts[4]);
+        assertEquals("PCL[];PCL[a.dex:b.dex:base.dex]", contexts[5]);
+        assertEquals("PCL[];PCL[base-5.dex];PCL[a.dex:b.dex:base.dex]", contexts[6]);
+        assertEquals(null, contexts[7]);
+    }
+
+    @Test
     public void testProcessContextForDexLoad() {
         List<String> classLoaders = Arrays.asList(
                 DELEGATE_LAST_CLASS_LOADER_NAME,
@@ -284,4 +373,49 @@
         }
         assertTrue(gotException);
     }
+
+    @Test
+    public void testEncodeClassLoader() {
+        assertEquals(SKIP_SHARED_LIBRARY_CHECK, DexoptUtils.encodeClassLoader(
+                SKIP_SHARED_LIBRARY_CHECK, "dalvik.system.PathClassLoader"));
+        assertEquals(SKIP_SHARED_LIBRARY_CHECK, DexoptUtils.encodeClassLoader(
+                SKIP_SHARED_LIBRARY_CHECK, "dalvik.system.DexClassLoader"));
+        assertEquals(SKIP_SHARED_LIBRARY_CHECK, DexoptUtils.encodeClassLoader(
+                SKIP_SHARED_LIBRARY_CHECK, "dalvik.system.DelegateLastClassLoader"));
+        assertEquals("PCL[xyz]", DexoptUtils.encodeClassLoader("xyz",
+                "dalvik.system.PathClassLoader"));
+        assertEquals("PCL[xyz]", DexoptUtils.encodeClassLoader("xyz",
+                "dalvik.system.DexClassLoader"));
+        assertEquals("DLC[xyz]", DexoptUtils.encodeClassLoader("xyz",
+                "dalvik.system.DelegateLastClassLoader"));
+        assertEquals("PCL[xyz]", DexoptUtils.encodeClassLoader("xyz", null));
+        assertEquals("abc[xyz]", DexoptUtils.encodeClassLoader("xyz", "abc"));
+
+        try {
+            DexoptUtils.encodeClassLoader(null, "abc");
+            fail(); // Exception should be caught.
+        } catch (NullPointerException expected) {}
+    }
+
+    @Test
+    public void testEncodeClassLoaderChain() {
+        assertEquals(SKIP_SHARED_LIBRARY_CHECK, DexoptUtils.encodeClassLoaderChain(
+                SKIP_SHARED_LIBRARY_CHECK, "PCL[a]"));
+        assertEquals(SKIP_SHARED_LIBRARY_CHECK, DexoptUtils.encodeClassLoaderChain("PCL[a]",
+                SKIP_SHARED_LIBRARY_CHECK));
+        assertEquals("PCL[a];DLC[b]", DexoptUtils.encodeClassLoaderChain("PCL[a]",
+                "DLC[b]"));
+        assertEquals(SKIP_SHARED_LIBRARY_CHECK, DexoptUtils.encodeClassLoaderChain("PCL[a]",
+                SKIP_SHARED_LIBRARY_CHECK));
+
+        try {
+            DexoptUtils.encodeClassLoaderChain("a", null);
+            fail(); // exception is expected
+        } catch (NullPointerException expected) {}
+
+        try {
+            DexoptUtils.encodeClassLoaderChain(null, "b");
+            fail(); // exception is expected
+        } catch (NullPointerException expected) {}
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index d12c07a..7c31e80 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -32,6 +32,10 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
+import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
+import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING;
+import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING;
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.eq;
@@ -92,4 +96,33 @@
         int reason = mService.getLastShutdownReasonInternal(mTempReason);
         assertThat(reason).isEqualTo(PowerManager.SHUTDOWN_REASON_THERMAL_SHUTDOWN);
     }
+
+    @SmallTest
+    public void testGetDesiredScreenPolicy_WithVR() throws Exception {
+        // Brighten up the screen
+        mService.setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);
+        assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
+                DisplayPowerRequest.POLICY_BRIGHT);
+
+        // Move to VR
+        mService.setVrModeEnabled(true);
+        assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
+                DisplayPowerRequest.POLICY_VR);
+
+        // Then take a nap
+        mService.setWakefulnessLocked(WAKEFULNESS_ASLEEP, 0);
+        assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
+                DisplayPowerRequest.POLICY_OFF);
+
+        // Wake up to VR
+        mService.setWakefulnessLocked(WAKEFULNESS_AWAKE, 0);
+        assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
+                DisplayPowerRequest.POLICY_VR);
+
+        // And back to normal
+        mService.setVrModeEnabled(false);
+        assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
+                DisplayPowerRequest.POLICY_BRIGHT);
+
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java
index 2887e3b..d09d0c8 100644
--- a/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java
@@ -585,7 +585,39 @@
         verifyNoPackageTrackerCallsMade();
 
         // Set up the installer.
-        configureStageUninstallExpectation(true /* success */);
+        configureStageUninstallExpectation(TimeZoneDistroInstaller.UNINSTALL_SUCCESS);
+
+        // Simulate the async execution.
+        mFakeExecutor.simulateAsyncExecutionOfLastCommand();
+
+        // Verify the expected calls were made to other components.
+        verifyStageUninstallCalled();
+        verifyPackageTrackerCalled(token, true /* success */);
+
+        // Check the callback was called.
+        callback.assertResultReceived(Callback.SUCCESS);
+    }
+
+    @Test
+    public void requestUninstall_asyncNothingInstalled() throws Exception {
+        configureCallerHasPermission();
+
+        CheckToken token = createArbitraryToken();
+        byte[] tokenBytes = token.toByteArray();
+
+        TestCallback callback = new TestCallback();
+
+        // Request the uninstall.
+        assertEquals(RulesManager.SUCCESS,
+                mRulesManagerService.requestUninstall(tokenBytes, callback));
+
+        // Assert nothing has happened yet.
+        callback.assertNoResultReceived();
+        verifyNoInstallerCallsMade();
+        verifyNoPackageTrackerCallsMade();
+
+        // Set up the installer.
+        configureStageUninstallExpectation(TimeZoneDistroInstaller.UNINSTALL_NOTHING_INSTALLED);
 
         // Simulate the async execution.
         mFakeExecutor.simulateAsyncExecutionOfLastCommand();
@@ -613,7 +645,7 @@
         callback.assertNoResultReceived();
 
         // Set up the installer.
-        configureStageUninstallExpectation(true /* success */);
+        configureStageUninstallExpectation(TimeZoneDistroInstaller.UNINSTALL_SUCCESS);
 
         // Simulate the async execution.
         mFakeExecutor.simulateAsyncExecutionOfLastCommand();
@@ -644,7 +676,7 @@
         callback.assertNoResultReceived();
 
         // Set up the installer.
-        configureStageUninstallExpectation(false /* success */);
+        configureStageUninstallExpectation(TimeZoneDistroInstaller.UNINSTALL_FAIL);
 
         // Simulate the async execution.
         mFakeExecutor.simulateAsyncExecutionOfLastCommand();
@@ -849,8 +881,8 @@
                 .thenReturn(resultCode);
     }
 
-    private void configureStageUninstallExpectation(boolean success) throws Exception {
-        doReturn(success).when(mMockTimeZoneDistroInstaller).stageUninstall();
+    private void configureStageUninstallExpectation(int resultCode) throws Exception {
+        doReturn(resultCode).when(mMockTimeZoneDistroInstaller).stageUninstall();
     }
 
     private void verifyStageInstallCalled() throws Exception {
diff --git a/telecomm/java/android/telecom/DefaultDialerManager.java b/telecomm/java/android/telecom/DefaultDialerManager.java
index 2a707c9..1806aee 100644
--- a/telecomm/java/android/telecom/DefaultDialerManager.java
+++ b/telecomm/java/android/telecom/DefaultDialerManager.java
@@ -22,6 +22,7 @@
 import android.content.pm.ResolveInfo;
 import android.net.Uri;
 import android.os.Process;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.TextUtils;
 
@@ -163,7 +164,10 @@
 
         for (ResolveInfo resolveInfo : resolveInfoList) {
             final ActivityInfo activityInfo = resolveInfo.activityInfo;
-            if (activityInfo != null && !packageNames.contains(activityInfo.packageName)) {
+            if (activityInfo != null
+                    && !packageNames.contains(activityInfo.packageName)
+                    // ignore cross profile intent handler
+                    && resolveInfo.targetUserId == UserHandle.USER_CURRENT) {
                 packageNames.add(activityInfo.packageName);
             }
         }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 63d492a..c36b3ac 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1762,7 +1762,11 @@
 
         // Carrier Signalling Receivers
         sDefaults.putString(KEY_CARRIER_SETUP_APP_STRING, "");
-        sDefaults.putStringArray(KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY, null);
+        sDefaults.putStringArray(KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
+                new String[]{
+                        "com.android.carrierdefaultapp/.CarrierDefaultBroadcastReceiver:"
+                                + "com.android.internal.telephony.CARRIER_SIGNAL_RESET"
+                });
         sDefaults.putStringArray(KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY, null);
 
 
diff --git a/telephony/java/android/telephony/MbmsDownloadManager.java b/telephony/java/android/telephony/MbmsDownloadManager.java
deleted file mode 100644
index 4c3f7e7..0000000
--- a/telephony/java/android/telephony/MbmsDownloadManager.java
+++ /dev/null
@@ -1,654 +0,0 @@
-/*
- * Copyright (C) 2016 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.telephony;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.SharedPreferences;
-import android.content.pm.ResolveInfo;
-import android.net.Uri;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.telephony.mbms.FileInfo;
-import android.telephony.mbms.DownloadRequest;
-import android.telephony.mbms.IDownloadProgressListener;
-import android.telephony.mbms.IMbmsDownloadManagerCallback;
-import android.telephony.mbms.MbmsDownloadManagerCallback;
-import android.telephony.mbms.MbmsDownloadReceiver;
-import android.telephony.mbms.MbmsException;
-import android.telephony.mbms.MbmsTempFileProvider;
-import android.telephony.mbms.MbmsUtils;
-import android.telephony.mbms.vendor.IMbmsDownloadService;
-import android.util.Log;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
-
-import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-
-/** @hide */
-public class MbmsDownloadManager {
-    private static final String LOG_TAG = MbmsDownloadManager.class.getSimpleName();
-
-    public static final String MBMS_DOWNLOAD_SERVICE_ACTION =
-            "android.telephony.action.EmbmsDownload";
-    /**
-     * The MBMS middleware should send this when a download of single file has completed or
-     * failed. Mandatory extras are
-     * {@link #EXTRA_RESULT}
-     * {@link #EXTRA_FILE_INFO}
-     * {@link #EXTRA_REQUEST}
-     * {@link #EXTRA_TEMP_LIST}
-     * {@link #EXTRA_FINAL_URI}
-     *
-     * TODO: future systemapi
-     */
-    public static final String ACTION_DOWNLOAD_RESULT_INTERNAL =
-            "android.telephony.mbms.action.DOWNLOAD_RESULT_INTERNAL";
-
-    /**
-     * The MBMS middleware should send this when it wishes to request {@code content://} URIs to
-     * serve as temp files for downloads or when it wishes to resume paused downloads. Mandatory
-     * extras are
-     * {@link #EXTRA_REQUEST}
-     *
-     * Optional extras are
-     * {@link #EXTRA_FD_COUNT} (0 if not present)
-     * {@link #EXTRA_PAUSED_LIST} (empty if not present)
-     *
-     * TODO: future systemapi
-     */
-    public static final String ACTION_FILE_DESCRIPTOR_REQUEST =
-            "android.telephony.mbms.action.FILE_DESCRIPTOR_REQUEST";
-
-    /**
-     * The MBMS middleware should send this when it wishes to clean up temp  files in the app's
-     * filesystem. Mandatory extras are:
-     * {@link #EXTRA_TEMP_FILES_IN_USE}
-     *
-     * TODO: future systemapi
-     */
-    public static final String ACTION_CLEANUP =
-            "android.telephony.mbms.action.CLEANUP";
-
-    /**
-     * Integer extra indicating the result code of the download. One of
-     * {@link #RESULT_SUCCESSFUL}, {@link #RESULT_EXPIRED}, or {@link #RESULT_CANCELLED}.
-     * TODO: Not systemapi.
-     */
-    public static final String EXTRA_RESULT = "android.telephony.mbms.extra.RESULT";
-
-    /**
-     * Extra containing the {@link android.telephony.mbms.FileInfo} for which the download result
-     * is for. Must not be null.
-     * TODO: Not systemapi.
-     */
-    public static final String EXTRA_FILE_INFO = "android.telephony.mbms.extra.FILE_INFO";
-
-    /**
-     * Extra containing the {@link DownloadRequest} for which the download result or file
-     * descriptor request is for. Must not be null.
-     * TODO: future systemapi (here and and all extras) except the three for the app intent
-     */
-    public static final String EXTRA_REQUEST = "android.telephony.mbms.extra.REQUEST";
-
-    /**
-     * Extra containing a {@link List} of {@link Uri}s that were used as temp files for this
-     * completed file. These {@link Uri}s should have scheme {@code file://}, and the temp
-     * files will be deleted upon receipt of the intent.
-     * May be null.
-     */
-    public static final String EXTRA_TEMP_LIST = "android.telephony.mbms.extra.TEMP_LIST";
-
-    /**
-     * Extra containing a single {@link Uri} indicating the path to the temp file in which the
-     * decoded downloaded file resides. Must not be null.
-     */
-    public static final String EXTRA_FINAL_URI = "android.telephony.mbms.extra.FINAL_URI";
-
-    /**
-     * Extra containing an integer indicating the number of temp files requested.
-     */
-    public static final String EXTRA_FD_COUNT = "android.telephony.mbms.extra.FD_COUNT";
-
-    /**
-     * Extra containing a list of {@link Uri}s that the middleware is requesting access to via
-     * {@link #ACTION_FILE_DESCRIPTOR_REQUEST} in order to resume downloading. These {@link Uri}s
-     * should have scheme {@code file://}.
-     */
-    public static final String EXTRA_PAUSED_LIST = "android.telephony.mbms.extra.PAUSED_LIST";
-
-    /**
-     * Extra containing a list of {@link android.telephony.mbms.UriPathPair}s, used in the
-     * response to {@link #ACTION_FILE_DESCRIPTOR_REQUEST}. These are temp files that are meant
-     * to be used for new file downloads.
-     */
-    public static final String EXTRA_FREE_URI_LIST = "android.telephony.mbms.extra.FREE_URI_LIST";
-
-    /**
-     * Extra containing a list of {@link android.telephony.mbms.UriPathPair}s, used in the
-     * response to {@link #ACTION_FILE_DESCRIPTOR_REQUEST}. These
-     * {@link android.telephony.mbms.UriPathPair}s contain {@code content://} URIs that provide
-     * access to previously paused downloads.
-     */
-    public static final String EXTRA_PAUSED_URI_LIST =
-            "android.telephony.mbms.extra.PAUSED_URI_LIST";
-
-    /**
-     * Extra containing a string that points to the middleware's knowledge of where the temp file
-     * root for the app is. The path should be a canonical path as returned by
-     * {@link File#getCanonicalPath()}
-     */
-    public static final String EXTRA_TEMP_FILE_ROOT =
-            "android.telephony.mbms.extra.TEMP_FILE_ROOT";
-
-    /**
-     * Extra containing a list of {@link Uri}s indicating temp files which the middleware is
-     * still using.
-     */
-    public static final String EXTRA_TEMP_FILES_IN_USE =
-            "android.telephony.mbms.extra.TEMP_FILES_IN_USE";
-
-    /**
-     * Extra containing an instance of {@link android.telephony.mbms.ServiceInfo}, used by
-     * file-descriptor requests and cleanup requests to specify which service they want to
-     * request temp files or clean up temp files for, respectively.
-     */
-    public static final String EXTRA_SERVICE_INFO =
-            "android.telephony.mbms.extra.SERVICE_INFO";
-
-    /**
-     * Extra containing a single {@link Uri} indicating the location of the successfully
-     * downloaded file. Set on the intent provided via
-     * {@link android.telephony.mbms.DownloadRequest.Builder#setAppIntent(Intent)}.
-     * Will always be set to a non-null value if {@link #EXTRA_RESULT} is set to
-     * {@link #RESULT_SUCCESSFUL}.
-     * TODO: Not systemapi.
-     */
-    public static final String EXTRA_COMPLETED_FILE_URI =
-            "android.telephony.mbms.extra.COMPLETED_FILE_URI";
-
-    public static final int RESULT_SUCCESSFUL = 1;
-    public static final int RESULT_CANCELLED  = 2;
-    public static final int RESULT_EXPIRED    = 3;
-    // TODO - more results!
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({STATUS_UNKNOWN, STATUS_ACTIVELY_DOWNLOADING, STATUS_PENDING_DOWNLOAD,
-            STATUS_PENDING_REPAIR, STATUS_PENDING_DOWNLOAD_WINDOW})
-    public @interface DownloadStatus {}
-
-    public static final int STATUS_UNKNOWN = 0;
-    public static final int STATUS_ACTIVELY_DOWNLOADING = 1;
-    public static final int STATUS_PENDING_DOWNLOAD = 2;
-    public static final int STATUS_PENDING_REPAIR = 3;
-    public static final int STATUS_PENDING_DOWNLOAD_WINDOW = 4;
-
-    private final Context mContext;
-    private int mSubscriptionId = INVALID_SUBSCRIPTION_ID;
-
-    private AtomicReference<IMbmsDownloadService> mService = new AtomicReference<>(null);
-    private final MbmsDownloadManagerCallback mCallback;
-
-    private MbmsDownloadManager(Context context, MbmsDownloadManagerCallback callback, int subId) {
-        mContext = context;
-        mCallback = callback;
-        mSubscriptionId = subId;
-    }
-
-    /**
-     * Create a new MbmsDownloadManager using the system default data subscription ID.
-     * See {@link #create(Context, MbmsDownloadManagerCallback, int)}
-     *
-     * @hide
-     */
-    public static MbmsDownloadManager create(Context context,
-            MbmsDownloadManagerCallback listener)
-            throws MbmsException {
-        return create(context, listener, SubscriptionManager.getDefaultSubscriptionId());
-    }
-
-    /**
-     * Create a new MbmsDownloadManager using the given subscription ID.
-     *
-     * Note that this call will bind a remote service and that may take a bit. The instance of
-     * {@link MbmsDownloadManager} that is returned will not be ready for use until
-     * {@link IMbmsDownloadManagerCallback#middlewareReady()} is called on the provided callback.
-     * If you attempt to use the manager before it is ready, a {@link MbmsException} will be thrown.
-     *
-     * This also may throw an {@link IllegalArgumentException} or a {@link MbmsException}.
-     *
-     * @param context The instance of {@link Context} to use
-     * @param listener A callback to get asynchronous error messages and file service updates.
-     * @param subscriptionId The data subscription ID to use
-     * @hide
-     */
-    public static MbmsDownloadManager create(Context context,
-            MbmsDownloadManagerCallback listener, int subscriptionId)
-            throws MbmsException {
-        MbmsDownloadManager mdm = new MbmsDownloadManager(context, listener, subscriptionId);
-        mdm.bindAndInitialize();
-        return mdm;
-    }
-
-    private void bindAndInitialize() throws MbmsException {
-        MbmsUtils.startBinding(mContext, MBMS_DOWNLOAD_SERVICE_ACTION,
-                new ServiceConnection() {
-                    @Override
-                    public void onServiceConnected(ComponentName name, IBinder service) {
-                        IMbmsDownloadService downloadService =
-                                IMbmsDownloadService.Stub.asInterface(service);
-                        int result;
-                        try {
-                            result = downloadService.initialize(mSubscriptionId, mCallback);
-                        } catch (RemoteException e) {
-                            Log.e(LOG_TAG, "Service died before initialization");
-                            return;
-                        } catch (RuntimeException e) {
-                            Log.e(LOG_TAG, "Runtime exception during initialization");
-                            mCallback.error(
-                                    MbmsException.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
-                                    e.toString());
-                            return;
-                        }
-                        if (result != MbmsException.SUCCESS) {
-                            mCallback.error(result, "Error returned during initialization");
-                            return;
-                        }
-                        mService.set(downloadService);
-                    }
-
-                    @Override
-                    public void onServiceDisconnected(ComponentName name) {
-                        mService.set(null);
-                    }
-                });
-    }
-
-    /**
-     * An inspection API to retrieve the list of available
-     * {@link android.telephony.mbms.FileServiceInfo}s currently being advertised.
-     * The results are returned asynchronously via a call to
-     * {@link IMbmsDownloadManagerCallback#fileServicesUpdated(List)}
-     *
-     * The serviceClasses argument lets the app filter on types of programming and is opaque data
-     * negotiated beforehand between the app and the carrier.
-     *
-     * This may throw an {@link MbmsException} containing one of the following errors:
-     * {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND}
-     * {@link MbmsException#ERROR_MIDDLEWARE_LOST}
-     *
-     * Asynchronous error codes via the {@link MbmsDownloadManagerCallback#error(int, String)}
-     * callback can include any of the errors except:
-     * {@link MbmsException.StreamingErrors#ERROR_UNABLE_TO_START_SERVICE}
-     *
-     * @param classList A list of service classes which the app wishes to receive
-     *                  {@link IMbmsDownloadManagerCallback#fileServicesUpdated(List)} callbacks
-     *                  about. Subsequent calls to this method will replace this list of service
-     *                  classes (i.e. the middleware will no longer send updates for services
-     *                  matching classes only in the old list).
-     */
-    public void getFileServices(List<String> classList) throws MbmsException {
-        IMbmsDownloadService downloadService = mService.get();
-        if (downloadService == null) {
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
-        }
-        try {
-            int returnCode = downloadService.getFileServices(mSubscriptionId, classList);
-            if (returnCode != MbmsException.SUCCESS) {
-                throw new MbmsException(returnCode);
-            }
-        } catch (RemoteException e) {
-            Log.w(LOG_TAG, "Remote process died");
-            mService.set(null);
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
-        }
-    }
-
-    /**
-     * Sets the temp file root for downloads.
-     * All temp files created for the middleware to write to will be contained in the specified
-     * directory. Applications that wish to specify a location only need to call this method once
-     * as long their data is persisted in storage -- the argument will be stored both in a
-     * local instance of {@link android.content.SharedPreferences} and by the middleware.
-     *
-     * If this method is not called at least once before calling
-     * {@link #download(DownloadRequest, IDownloadCallback)}, the framework
-     * will default to a directory formed by the concatenation of the app's files directory and
-     * {@link android.telephony.mbms.MbmsTempFileProvider#DEFAULT_TOP_LEVEL_TEMP_DIRECTORY}.
-     *
-     * Before calling this method, the app must cancel all of its pending
-     * {@link DownloadRequest}s via {@link #cancelDownload(DownloadRequest)}. If this is not done,
-     * an {@link MbmsException} will be thrown with code
-     * {@link MbmsException.DownloadErrors#ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT}
-     *
-     * The {@link File} supplied as a root temp file directory must already exist. If not, an
-     * {@link IllegalArgumentException} will be thrown.
-     * @param tempFileRootDirectory A directory to place temp files in.
-     */
-    public void setTempFileRootDirectory(@NonNull File tempFileRootDirectory)
-            throws MbmsException {
-        IMbmsDownloadService downloadService = mService.get();
-        if (downloadService == null) {
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
-        }
-        if (!tempFileRootDirectory.exists()) {
-            throw new IllegalArgumentException("Provided directory does not exist");
-        }
-        if (!tempFileRootDirectory.isDirectory()) {
-            throw new IllegalArgumentException("Provided File is not a directory");
-        }
-        String filePath;
-        try {
-            filePath = tempFileRootDirectory.getCanonicalPath();
-        } catch (IOException e) {
-            throw new IllegalArgumentException("Unable to canonicalize the provided path: " + e);
-        }
-
-        try {
-            int result = downloadService.setTempFileRootDirectory(mSubscriptionId, filePath);
-            if (result != MbmsException.SUCCESS) {
-                throw new MbmsException(result);
-            }
-        } catch (RemoteException e) {
-            mService.set(null);
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
-        }
-
-        SharedPreferences prefs = mContext.getSharedPreferences(
-                MbmsTempFileProvider.TEMP_FILE_ROOT_PREF_FILE_NAME, 0);
-        prefs.edit().putString(MbmsTempFileProvider.TEMP_FILE_ROOT_PREF_NAME, filePath).apply();
-    }
-
-    /**
-     * Requests a download of a file that is available via multicast.
-     *
-     * downloadListener is an optional callback object which can be used to get progress reports
-     *     of a currently occuring download.  Note this can only run while the calling app
-     *     is running, so future downloads will simply result in resultIntents being sent
-     *     for completed or errored-out downloads.  A NULL indicates no callbacks are needed.
-     *
-     * May throw an {@link IllegalArgumentException}
-     *
-     * If {@link #setTempFileRootDirectory(File)} has not called after the app has been installed,
-     * this method will create a directory at the default location defined at
-     * {@link MbmsTempFileProvider#DEFAULT_TOP_LEVEL_TEMP_DIRECTORY} and store that as the temp
-     * file root directory.
-     *
-     * Asynchronous errors through the listener include any of the errors
-     *
-     * @param request The request that specifies what should be downloaded
-     * @param progressListener Optional listener that will be provided progress updates
-     *                         if the app is running.
-     */
-    public void download(DownloadRequest request, IDownloadProgressListener progressListener)
-            throws MbmsException {
-        IMbmsDownloadService downloadService = mService.get();
-        if (downloadService == null) {
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
-        }
-
-        // Check to see whether the app's set a temp root dir yet, and set it if not.
-        SharedPreferences prefs = mContext.getSharedPreferences(
-                MbmsTempFileProvider.TEMP_FILE_ROOT_PREF_FILE_NAME, 0);
-        if (prefs.getString(MbmsTempFileProvider.TEMP_FILE_ROOT_PREF_NAME, null) == null) {
-            File tempRootDirectory = new File(mContext.getFilesDir(),
-                    MbmsTempFileProvider.DEFAULT_TOP_LEVEL_TEMP_DIRECTORY);
-            tempRootDirectory.mkdirs();
-            setTempFileRootDirectory(tempRootDirectory);
-        }
-
-        checkValidDownloadDestination(request);
-        writeDownloadRequestToken(request);
-        try {
-            downloadService.download(request, progressListener);
-        } catch (RemoteException e) {
-            mService.set(null);
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
-        }
-    }
-
-    /**
-     * Returns a list of pending {@link DownloadRequest}s that originated from this application.
-     * A pending request is one that was issued via
-     * {@link #download(DownloadRequest, IDownloadCallback)} but not cancelled through
-     * {@link #cancelDownload(DownloadRequest)}.
-     * @return A list, possibly empty, of {@link DownloadRequest}s
-     */
-    public @NonNull List<DownloadRequest> listPendingDownloads() throws MbmsException {
-        IMbmsDownloadService downloadService = mService.get();
-        if (downloadService == null) {
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
-        }
-
-        try {
-            return downloadService.listPendingDownloads(mSubscriptionId);
-        } catch (RemoteException e) {
-            mService.set(null);
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
-        }
-    }
-
-    /**
-     * Attempts to cancel the specified {@link DownloadRequest}.
-     *
-     * If the middleware is not aware of the specified download request, an MbmsException will be
-     * thrown with error code {@link MbmsException.DownloadErrors#ERROR_UNKNOWN_DOWNLOAD_REQUEST}.
-     *
-     * If this method returns without throwing an exception, you may assume that cancellation
-     * was successful.
-     * @param downloadRequest The download request that you wish to cancel.
-     */
-    public void cancelDownload(DownloadRequest downloadRequest) throws MbmsException {
-        IMbmsDownloadService downloadService = mService.get();
-        if (downloadService == null) {
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
-        }
-
-        try {
-            int result = downloadService.cancelDownload(downloadRequest);
-            if (result != MbmsException.SUCCESS) {
-                throw new MbmsException(result);
-            }
-        } catch (RemoteException e) {
-            mService.set(null);
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
-        }
-        deleteDownloadRequestToken(downloadRequest);
-    }
-
-    /**
-     * Gets information about the status of a file pending download.
-     *
-     * If the middleware has not yet been properly initialized or if it has no records of the
-     * file indicated by {@code fileInfo} being associated with {@code downloadRequest},
-     * {@link #STATUS_UNKNOWN} will be returned.
-     *
-     * @param downloadRequest The download request to query.
-     * @param fileInfo The particular file within the request to get information on.
-     * @return The status of the download.
-     */
-    @DownloadStatus
-    public int getDownloadStatus(DownloadRequest downloadRequest, FileInfo fileInfo)
-            throws MbmsException {
-        IMbmsDownloadService downloadService = mService.get();
-        if (downloadService == null) {
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
-        }
-
-        try {
-            return downloadService.getDownloadStatus(downloadRequest, fileInfo);
-        } catch (RemoteException e) {
-            mService.set(null);
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
-        }
-    }
-
-    /**
-     * Resets the middleware's knowledge of previously-downloaded files in this download request.
-     *
-     * Normally, the middleware keeps track of the hashes of downloaded files and won't re-download
-     * files whose server-reported hash matches one of the already-downloaded files. This means
-     * that if the file is accidentally deleted by the user or by the app, the middleware will
-     * not try to download it again.
-     * This method will reset the middleware's cache of hashes for the provided
-     * {@link DownloadRequest}, so that previously downloaded content will be downloaded again
-     * when available.
-     * This will not interrupt in-progress downloads.
-     *
-     * If the middleware is not aware of the specified download request, an MbmsException will be
-     * thrown with error code {@link MbmsException.DownloadErrors#ERROR_UNKNOWN_DOWNLOAD_REQUEST}.
-     *
-     * May throw a {@link MbmsException} with error code
-     * @param downloadRequest The request to re-download files for.
-     */
-    public void resetDownloadKnowledge(DownloadRequest downloadRequest) throws MbmsException {
-        IMbmsDownloadService downloadService = mService.get();
-        if (downloadService == null) {
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
-        }
-
-        try {
-            int result = downloadService.resetDownloadKnowledge(downloadRequest);
-            if (result != MbmsException.SUCCESS) {
-                throw new MbmsException(result);
-            }
-        } catch (RemoteException e) {
-            mService.set(null);
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
-        }
-    }
-
-    public void dispose() {
-        try {
-            IMbmsDownloadService downloadService = mService.get();
-            if (downloadService == null) {
-                Log.i(LOG_TAG, "Service already dead");
-                return;
-            }
-            downloadService.dispose(mSubscriptionId);
-            mService.set(null);
-        } catch (RemoteException e) {
-            // Ignore
-            Log.i(LOG_TAG, "Remote exception while disposing of service");
-        }
-    }
-
-    /**
-     * Retrieves the {@link ComponentName} for the {@link android.content.BroadcastReceiver} that
-     * the various intents from the middleware should be targeted towards.
-     * @param uid The uid of the frontend app.
-     * @return The component name of the receiver that the middleware should send its intents to,
-     * or null if the app didn't declare it in the manifest.
-     *
-     * @hide
-     * future systemapi
-     */
-    public static ComponentName getAppReceiverFromUid(Context context, int uid) {
-        String[] packageNames = context.getPackageManager().getPackagesForUid(uid);
-        if (packageNames == null) {
-            return null;
-        }
-
-        for (String packageName : packageNames) {
-            ComponentName candidate = new ComponentName(packageName,
-                    MbmsDownloadReceiver.class.getCanonicalName());
-            Intent queryIntent = new Intent();
-            queryIntent.setComponent(candidate);
-            List<ResolveInfo> receivers =
-                    context.getPackageManager().queryBroadcastReceivers(queryIntent, 0);
-            if (receivers != null && receivers.size() > 0) {
-                return candidate;
-            }
-        }
-        return null;
-    }
-
-    private void writeDownloadRequestToken(DownloadRequest request) {
-        File token = getDownloadRequestTokenPath(request);
-        if (!token.getParentFile().exists()) {
-            token.getParentFile().mkdirs();
-        }
-        if (token.exists()) {
-            Log.w(LOG_TAG, "Download token " + token.getName() + " already exists");
-            return;
-        }
-        try {
-            if (!token.createNewFile()) {
-                throw new RuntimeException("Failed to create download token for request "
-                        + request);
-            }
-        } catch (IOException e) {
-            throw new RuntimeException("Failed to create download token for request " + request
-                    + " due to IOException " + e);
-        }
-    }
-
-    private void deleteDownloadRequestToken(DownloadRequest request) {
-        File token = getDownloadRequestTokenPath(request);
-        if (!token.isFile()) {
-            Log.w(LOG_TAG, "Attempting to delete non-existent download token at " + token);
-            return;
-        }
-        if (!token.delete()) {
-            Log.w(LOG_TAG, "Couldn't delete download token at " + token);
-        }
-    }
-
-    private File getDownloadRequestTokenPath(DownloadRequest request) {
-        File tempFileLocation = MbmsUtils.getEmbmsTempFileDirForService(mContext,
-                request.getFileServiceId());
-        String downloadTokenFileName = request.getHash()
-                + MbmsDownloadReceiver.DOWNLOAD_TOKEN_SUFFIX;
-        return new File(tempFileLocation, downloadTokenFileName);
-    }
-
-    /**
-     * Verifies the following:
-     * If a request is multi-part,
-     *     1. Destination Uri must exist and be a directory
-     *     2. Directory specified must contain no files.
-     * Otherwise
-     *     1. The file specified by the destination Uri must not exist.
-     */
-    private void checkValidDownloadDestination(DownloadRequest request) {
-        File toFile = new File(request.getDestinationUri().getSchemeSpecificPart());
-        if (request.isMultipartDownload()) {
-            if (!toFile.isDirectory()) {
-                throw new IllegalArgumentException("Multipart download must specify valid " +
-                        "destination directory.");
-            }
-            if (toFile.listFiles().length > 0) {
-                throw new IllegalArgumentException("Destination directory must be clear of all " +
-                        "files.");
-            }
-        } else {
-            if (toFile.exists()) {
-                throw new IllegalArgumentException("Destination file must not exist.");
-            }
-        }
-    }
-}
diff --git a/telephony/java/android/telephony/MbmsDownloadSession.java b/telephony/java/android/telephony/MbmsDownloadSession.java
new file mode 100644
index 0000000..01ed690
--- /dev/null
+++ b/telephony/java/android/telephony/MbmsDownloadSession.java
@@ -0,0 +1,774 @@
+/*
+ * Copyright (C) 2016 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.telephony;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.telephony.mbms.DownloadStateCallback;
+import android.telephony.mbms.FileInfo;
+import android.telephony.mbms.DownloadRequest;
+import android.telephony.mbms.InternalDownloadSessionCallback;
+import android.telephony.mbms.InternalDownloadStateCallback;
+import android.telephony.mbms.MbmsDownloadSessionCallback;
+import android.telephony.mbms.MbmsDownloadReceiver;
+import android.telephony.mbms.MbmsErrors;
+import android.telephony.mbms.MbmsTempFileProvider;
+import android.telephony.mbms.MbmsUtils;
+import android.telephony.mbms.vendor.IMbmsDownloadService;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+/**
+ * This class provides functionality for file download over MBMS.
+ * @hide
+ */
+public class MbmsDownloadSession implements AutoCloseable {
+    private static final String LOG_TAG = MbmsDownloadSession.class.getSimpleName();
+
+    /**
+     * Service action which must be handled by the middleware implementing the MBMS file download
+     * interface.
+     * @hide
+     */
+    //@SystemApi
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String MBMS_DOWNLOAD_SERVICE_ACTION =
+            "android.telephony.action.EmbmsDownload";
+
+    /**
+     * Integer extra that Android will attach to the intent supplied via
+     * {@link android.telephony.mbms.DownloadRequest.Builder#setAppIntent(Intent)}
+     * Indicates the result code of the download. One of
+     * {@link #RESULT_SUCCESSFUL}, {@link #RESULT_EXPIRED}, {@link #RESULT_CANCELLED}, or
+     * {@link #RESULT_IO_ERROR}.
+     *
+     * This extra may also be used by the middleware when it is sending intents to the app.
+     */
+    public static final String EXTRA_MBMS_DOWNLOAD_RESULT =
+            "android.telephony.extra.MBMS_DOWNLOAD_RESULT";
+
+    /**
+     * {@link FileInfo} extra that Android will attach to the intent supplied via
+     * {@link android.telephony.mbms.DownloadRequest.Builder#setAppIntent(Intent)}
+     * Indicates the file for which the download result is for. Never null.
+     *
+     * This extra may also be used by the middleware when it is sending intents to the app.
+     */
+    public static final String EXTRA_MBMS_FILE_INFO = "android.telephony.extra.MBMS_FILE_INFO";
+
+    /**
+     * {@link Uri} extra that Android will attach to the intent supplied via
+     * {@link android.telephony.mbms.DownloadRequest.Builder#setAppIntent(Intent)}
+     * Indicates the location of the successfully downloaded file within the temp file root set
+     * via {@link #setTempFileRootDirectory(File)}.
+     * While you may use this file in-place, it is highly encouraged that you move
+     * this file to a different location after receiving the download completion intent, as this
+     * file resides within the temp file directory.
+     *
+     * Will always be set to a non-null value if
+     * {@link #EXTRA_MBMS_DOWNLOAD_RESULT} is set to {@link #RESULT_SUCCESSFUL}.
+     */
+    public static final String EXTRA_MBMS_COMPLETED_FILE_URI =
+            "android.telephony.extra.MBMS_COMPLETED_FILE_URI";
+
+    /**
+     * Extra containing the {@link DownloadRequest} for which the download result or file
+     * descriptor request is for. Must not be null.
+     */
+    public static final String EXTRA_MBMS_DOWNLOAD_REQUEST =
+            "android.telephony.extra.MBMS_DOWNLOAD_REQUEST";
+
+    /**
+     * The default directory name for all MBMS temp files. If you call
+     * {@link #download(DownloadRequest)} without first calling
+     * {@link #setTempFileRootDirectory(File)}, this directory will be created for you under the
+     * path returned by {@link Context#getFilesDir()}.
+     */
+    public static final String DEFAULT_TOP_LEVEL_TEMP_DIRECTORY = "androidMbmsTempFileRoot";
+
+    /**
+     * Indicates that the download was successful.
+     */
+    public static final int RESULT_SUCCESSFUL = 1;
+
+    /**
+     * Indicates that the download was cancelled via {@link #cancelDownload(DownloadRequest)}.
+     */
+    public static final int RESULT_CANCELLED = 2;
+
+    /**
+     * Indicates that the download will not be completed due to the expiration of its download
+     * window on the carrier's network.
+     */
+    public static final int RESULT_EXPIRED = 3;
+
+    /**
+     * Indicates that the download will not be completed due to an I/O error incurred while
+     * writing to temp files. This commonly indicates that the device is out of storage space,
+     * but may indicate other conditions as well (such as an SD card being removed).
+     */
+    public static final int RESULT_IO_ERROR = 4;
+    // TODO - more results!
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({STATUS_UNKNOWN, STATUS_ACTIVELY_DOWNLOADING, STATUS_PENDING_DOWNLOAD,
+            STATUS_PENDING_REPAIR, STATUS_PENDING_DOWNLOAD_WINDOW})
+    public @interface DownloadStatus {}
+
+    /**
+     * Indicates that the middleware has no information on the file.
+     */
+    public static final int STATUS_UNKNOWN = 0;
+
+    /**
+     * Indicates that the file is actively downloading.
+     */
+    public static final int STATUS_ACTIVELY_DOWNLOADING = 1;
+
+    /**
+     * TODO: I don't know...
+     */
+    public static final int STATUS_PENDING_DOWNLOAD = 2;
+
+    /**
+     * Indicates that the file is being repaired after the download being interrupted.
+     */
+    public static final int STATUS_PENDING_REPAIR = 3;
+
+    /**
+     * Indicates that the file is waiting to download because its download window has not yet
+     * started.
+     */
+    public static final int STATUS_PENDING_DOWNLOAD_WINDOW = 4;
+
+    private static AtomicBoolean sIsInitialized = new AtomicBoolean(false);
+
+    private final Context mContext;
+    private int mSubscriptionId = INVALID_SUBSCRIPTION_ID;
+    private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
+        @Override
+        public void binderDied() {
+            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, "Received death notification");
+        }
+    };
+
+    private AtomicReference<IMbmsDownloadService> mService = new AtomicReference<>(null);
+    private final InternalDownloadSessionCallback mInternalCallback;
+    private final Map<DownloadStateCallback, InternalDownloadStateCallback>
+            mInternalDownloadCallbacks = new HashMap<>();
+
+    private MbmsDownloadSession(Context context, MbmsDownloadSessionCallback callback,
+            int subscriptionId, Handler handler) {
+        mContext = context;
+        mSubscriptionId = subscriptionId;
+        if (handler == null) {
+            handler = new Handler(Looper.getMainLooper());
+        }
+        mInternalCallback = new InternalDownloadSessionCallback(callback, handler);
+    }
+
+    /**
+     * Create a new {@link MbmsDownloadSession} using the system default data subscription ID.
+     * See {@link #create(Context, MbmsDownloadSessionCallback, int, Handler)}
+     */
+    public static MbmsDownloadSession create(@NonNull Context context,
+            @NonNull MbmsDownloadSessionCallback callback, @NonNull Handler handler) {
+        return create(context, callback, SubscriptionManager.getDefaultSubscriptionId(), handler);
+    }
+
+    /**
+     * Create a new MbmsDownloadManager using the given subscription ID.
+     *
+     * Note that this call will bind a remote service and that may take a bit. The instance of
+     * {@link MbmsDownloadSession} that is returned will not be ready for use until
+     * {@link MbmsDownloadSessionCallback#onMiddlewareReady()} is called on the provided callback.
+     * If you attempt to use the instance before it is ready, an {@link IllegalStateException}
+     * will be thrown or an error will be delivered through
+     * {@link MbmsDownloadSessionCallback#onError(int, String)}.
+     *
+     * This also may throw an {@link IllegalArgumentException}.
+     *
+     * You may only have one instance of {@link MbmsDownloadSession} per UID. If you call this
+     * method while there is an active instance of {@link MbmsDownloadSession} in your process
+     * (in other words, one that has not had {@link #close()} called on it), this method will
+     * throw an {@link IllegalStateException}. If you call this method in a different process
+     * running under the same UID, an error will be indicated via
+     * {@link MbmsDownloadSessionCallback#onError(int, String)}.
+     *
+     * Note that initialization may fail asynchronously. If you wish to try again after you
+     * receive such an asynchronous error, you must call {@link #close()} on the instance of
+     * {@link MbmsDownloadSession} that you received before calling this method again.
+     *
+     * @param context The instance of {@link Context} to use
+     * @param callback A callback to get asynchronous error messages and file service updates.
+     * @param subscriptionId The data subscription ID to use
+     * @param handler The {@link Handler} on which callbacks should be enqueued.
+     * @return A new instance of {@link MbmsDownloadSession}, or null if an error occurred during
+     * setup.
+     */
+    public static @Nullable MbmsDownloadSession create(@NonNull Context context,
+            final @NonNull MbmsDownloadSessionCallback callback,
+            int subscriptionId, @NonNull Handler handler) {
+        if (!sIsInitialized.compareAndSet(false, true)) {
+            throw new IllegalStateException("Cannot have two active instances");
+        }
+        MbmsDownloadSession session =
+                new MbmsDownloadSession(context, callback, subscriptionId, handler);
+        final int result = session.bindAndInitialize();
+        if (result != MbmsErrors.SUCCESS) {
+            sIsInitialized.set(false);
+            handler.post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onError(result, null);
+                }
+            });
+            return null;
+        }
+        return session;
+    }
+
+    private int bindAndInitialize() {
+        return MbmsUtils.startBinding(mContext, MBMS_DOWNLOAD_SERVICE_ACTION,
+                new ServiceConnection() {
+                    @Override
+                    public void onServiceConnected(ComponentName name, IBinder service) {
+                        IMbmsDownloadService downloadService =
+                                IMbmsDownloadService.Stub.asInterface(service);
+                        int result;
+                        try {
+                            result = downloadService.initialize(mSubscriptionId, mInternalCallback);
+                        } catch (RemoteException e) {
+                            Log.e(LOG_TAG, "Service died before initialization");
+                            sIsInitialized.set(false);
+                            return;
+                        } catch (RuntimeException e) {
+                            Log.e(LOG_TAG, "Runtime exception during initialization");
+                            sendErrorToApp(
+                                    MbmsErrors.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
+                                    e.toString());
+                            sIsInitialized.set(false);
+                            return;
+                        }
+                        if (result != MbmsErrors.SUCCESS) {
+                            sendErrorToApp(result, "Error returned during initialization");
+                            sIsInitialized.set(false);
+                            return;
+                        }
+                        try {
+                            downloadService.asBinder().linkToDeath(mDeathRecipient, 0);
+                        } catch (RemoteException e) {
+                            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST,
+                                    "Middleware lost during initialization");
+                            sIsInitialized.set(false);
+                            return;
+                        }
+                        mService.set(downloadService);
+                    }
+
+                    @Override
+                    public void onServiceDisconnected(ComponentName name) {
+                        sIsInitialized.set(false);
+                        mService.set(null);
+                    }
+                });
+    }
+
+    /**
+     * An inspection API to retrieve the list of available
+     * {@link android.telephony.mbms.FileServiceInfo}s currently being advertised.
+     * The results are returned asynchronously via a call to
+     * {@link MbmsDownloadSessionCallback#onFileServicesUpdated(List)}
+     *
+     * Asynchronous error codes via the {@link MbmsDownloadSessionCallback#onError(int, String)}
+     * callback may include any of the errors that are not specific to the streaming use-case.
+     *
+     * May throw an {@link IllegalStateException} or {@link IllegalArgumentException}.
+     *
+     * @param classList A list of service classes which the app wishes to receive
+     *                  {@link MbmsDownloadSessionCallback#onFileServicesUpdated(List)} callbacks
+     *                  about. Subsequent calls to this method will replace this list of service
+     *                  classes (i.e. the middleware will no longer send updates for services
+     *                  matching classes only in the old list).
+     *                  Values in this list should be negotiated with the wireless carrier prior
+     *                  to using this API.
+     */
+    public void requestUpdateFileServices(@NonNull List<String> classList) {
+        IMbmsDownloadService downloadService = mService.get();
+        if (downloadService == null) {
+            throw new IllegalStateException("Middleware not yet bound");
+        }
+        try {
+            int returnCode = downloadService.requestUpdateFileServices(mSubscriptionId, classList);
+            if (returnCode != MbmsErrors.SUCCESS) {
+                sendErrorToApp(returnCode, null);
+            }
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "Remote process died");
+            mService.set(null);
+            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
+        }
+    }
+
+    /**
+     * Sets the temp file root for downloads.
+     * All temp files created for the middleware to write to will be contained in the specified
+     * directory. Applications that wish to specify a location only need to call this method once
+     * as long their data is persisted in storage -- the argument will be stored both in a
+     * local instance of {@link android.content.SharedPreferences} and by the middleware.
+     *
+     * If this method is not called at least once before calling
+     * {@link #download(DownloadRequest)}, the framework
+     * will default to a directory formed by the concatenation of the app's files directory and
+     * {@link MbmsDownloadSession#DEFAULT_TOP_LEVEL_TEMP_DIRECTORY}.
+     *
+     * Before calling this method, the app must cancel all of its pending
+     * {@link DownloadRequest}s via {@link #cancelDownload(DownloadRequest)}. If this is not done,
+     * you will receive an asynchronous error with code
+     * {@link MbmsErrors.DownloadErrors#ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT} unless the
+     * provided directory is the same as what has been previously configured.
+     *
+     * The {@link File} supplied as a root temp file directory must already exist. If not, an
+     * {@link IllegalArgumentException} will be thrown. In addition, as an additional sanity
+     * check, an {@link IllegalArgumentException} will be thrown if you attempt to set the temp
+     * file root directory to one of your data roots (the value of {@link Context#getDataDir()},
+     * {@link Context#getFilesDir()}, or {@link Context#getCacheDir()}).
+     * @param tempFileRootDirectory A directory to place temp files in.
+     */
+    public void setTempFileRootDirectory(@NonNull File tempFileRootDirectory) {
+        IMbmsDownloadService downloadService = mService.get();
+        if (downloadService == null) {
+            throw new IllegalStateException("Middleware not yet bound");
+        }
+        try {
+            validateTempFileRootSanity(tempFileRootDirectory);
+        } catch (IOException e) {
+            throw new IllegalStateException("Got IOException checking directory sanity");
+        }
+        String filePath;
+        try {
+            filePath = tempFileRootDirectory.getCanonicalPath();
+        } catch (IOException e) {
+            throw new IllegalArgumentException("Unable to canonicalize the provided path: " + e);
+        }
+
+        try {
+            int result = downloadService.setTempFileRootDirectory(mSubscriptionId, filePath);
+            if (result != MbmsErrors.SUCCESS) {
+                sendErrorToApp(result, null);
+            }
+        } catch (RemoteException e) {
+            mService.set(null);
+            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
+            return;
+        }
+
+        SharedPreferences prefs = mContext.getSharedPreferences(
+                MbmsTempFileProvider.TEMP_FILE_ROOT_PREF_FILE_NAME, 0);
+        prefs.edit().putString(MbmsTempFileProvider.TEMP_FILE_ROOT_PREF_NAME, filePath).apply();
+    }
+
+    private void validateTempFileRootSanity(File tempFileRootDirectory) throws IOException {
+        if (!tempFileRootDirectory.exists()) {
+            throw new IllegalArgumentException("Provided directory does not exist");
+        }
+        if (!tempFileRootDirectory.isDirectory()) {
+            throw new IllegalArgumentException("Provided File is not a directory");
+        }
+        String canonicalTempFilePath = tempFileRootDirectory.getCanonicalPath();
+        if (mContext.getDataDir().getCanonicalPath().equals(canonicalTempFilePath)) {
+            throw new IllegalArgumentException("Temp file root cannot be your data dir");
+        }
+        if (mContext.getCacheDir().getCanonicalPath().equals(canonicalTempFilePath)) {
+            throw new IllegalArgumentException("Temp file root cannot be your cache dir");
+        }
+        if (mContext.getFilesDir().getCanonicalPath().equals(canonicalTempFilePath)) {
+            throw new IllegalArgumentException("Temp file root cannot be your files dir");
+        }
+    }
+    /**
+     * Retrieves the currently configured temp file root directory. Returns the file that was
+     * configured via {@link #setTempFileRootDirectory(File)} or the default directory
+     * {@link #download(DownloadRequest)} was called without ever
+     * setting the temp file root. If neither method has been called since the last time the app's
+     * shared preferences were reset, returns {@code null}.
+     *
+     * @return A {@link File} pointing to the configured temp file directory, or null if not yet
+     *         configured.
+     */
+    public @Nullable File getTempFileRootDirectory() {
+        SharedPreferences prefs = mContext.getSharedPreferences(
+                MbmsTempFileProvider.TEMP_FILE_ROOT_PREF_FILE_NAME, 0);
+        String path = prefs.getString(MbmsTempFileProvider.TEMP_FILE_ROOT_PREF_NAME, null);
+        if (path != null) {
+            return new File(path);
+        }
+        return null;
+    }
+
+    /**
+     * Requests the download of a file or set of files that the carrier has indicated to be
+     * available.
+     *
+     * May throw an {@link IllegalArgumentException}
+     *
+     * If {@link #setTempFileRootDirectory(File)} has not called after the app has been installed,
+     * this method will create a directory at the default location defined at
+     * {@link MbmsDownloadSession#DEFAULT_TOP_LEVEL_TEMP_DIRECTORY} and store that as the temp
+     * file root directory.
+     *
+     * Asynchronous errors through the callback may include any error not specific to the
+     * streaming use-case.
+     * @param request The request that specifies what should be downloaded.
+     */
+    public void download(@NonNull DownloadRequest request) {
+        IMbmsDownloadService downloadService = mService.get();
+        if (downloadService == null) {
+            throw new IllegalStateException("Middleware not yet bound");
+        }
+
+        // Check to see whether the app's set a temp root dir yet, and set it if not.
+        SharedPreferences prefs = mContext.getSharedPreferences(
+                MbmsTempFileProvider.TEMP_FILE_ROOT_PREF_FILE_NAME, 0);
+        if (prefs.getString(MbmsTempFileProvider.TEMP_FILE_ROOT_PREF_NAME, null) == null) {
+            File tempRootDirectory = new File(mContext.getFilesDir(),
+                    DEFAULT_TOP_LEVEL_TEMP_DIRECTORY);
+            tempRootDirectory.mkdirs();
+            setTempFileRootDirectory(tempRootDirectory);
+        }
+
+        writeDownloadRequestToken(request);
+        try {
+            downloadService.download(request);
+        } catch (RemoteException e) {
+            mService.set(null);
+            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
+        }
+    }
+
+    /**
+     * Returns a list of pending {@link DownloadRequest}s that originated from this application.
+     * A pending request is one that was issued via
+     * {@link #download(DownloadRequest)} but not cancelled through
+     * {@link #cancelDownload(DownloadRequest)}.
+     * @return A list, possibly empty, of {@link DownloadRequest}s
+     */
+    public @NonNull List<DownloadRequest> listPendingDownloads() {
+        IMbmsDownloadService downloadService = mService.get();
+        if (downloadService == null) {
+            throw new IllegalStateException("Middleware not yet bound");
+        }
+
+        try {
+            return downloadService.listPendingDownloads(mSubscriptionId);
+        } catch (RemoteException e) {
+            mService.set(null);
+            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
+            return Collections.emptyList();
+        }
+    }
+
+    /**
+     * Registers a callback for a {@link DownloadRequest} previously requested via
+     * {@link #download(DownloadRequest)}. This callback will only be called as long as both this
+     * app and the middleware are both running -- if either one stops, no further calls on the
+     * provided {@link DownloadStateCallback} will be enqueued.
+     *
+     * If the middleware is not aware of the specified download request,
+     * this method will throw an {@link IllegalArgumentException}.
+     *
+     * @param request The {@link DownloadRequest} that you want updates on.
+     * @param callback The callback that should be called when the middleware has information to
+     *                 share on the download.
+     * @param handler The {@link Handler} on which calls to {@code callback} should be enqueued on.
+     */
+    public void registerStateCallback(@NonNull DownloadRequest request,
+            @NonNull DownloadStateCallback callback,
+            @NonNull Handler handler) {
+        IMbmsDownloadService downloadService = mService.get();
+        if (downloadService == null) {
+            throw new IllegalStateException("Middleware not yet bound");
+        }
+
+        InternalDownloadStateCallback internalCallback =
+                new InternalDownloadStateCallback(callback, handler);
+
+        try {
+            int result = downloadService.registerStateCallback(request, internalCallback);
+            if (result != MbmsErrors.SUCCESS) {
+                if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) {
+                    throw new IllegalArgumentException("Unknown download request.");
+                }
+                sendErrorToApp(result, null);
+                return;
+            }
+        } catch (RemoteException e) {
+            mService.set(null);
+            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
+            return;
+        }
+        mInternalDownloadCallbacks.put(callback, internalCallback);
+    }
+
+    /**
+     * Un-register a callback previously registered via
+     * {@link #registerStateCallback(DownloadRequest, DownloadStateCallback, Handler)}. After
+     * this method is called, no further callbacks will be enqueued on the {@link Handler}
+     * provided upon registration, even if this method throws an exception.
+     *
+     * If the middleware is not aware of the specified download request,
+     * this method will throw an {@link IllegalArgumentException}.
+     *
+     * @param request The {@link DownloadRequest} provided during registration
+     * @param callback The callback provided during registration.
+     */
+    public void unregisterStateCallback(@NonNull DownloadRequest request,
+            @NonNull DownloadStateCallback callback) {
+        try {
+            IMbmsDownloadService downloadService = mService.get();
+            if (downloadService == null) {
+                throw new IllegalStateException("Middleware not yet bound");
+            }
+
+            InternalDownloadStateCallback internalCallback =
+                    mInternalDownloadCallbacks.get(callback);
+
+            try {
+                int result = downloadService.unregisterStateCallback(request, internalCallback);
+                if (result != MbmsErrors.SUCCESS) {
+                    if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) {
+                        throw new IllegalArgumentException("Unknown download request.");
+                    }
+                    sendErrorToApp(result, null);
+                }
+            } catch (RemoteException e) {
+                mService.set(null);
+                sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
+            }
+        } finally {
+            InternalDownloadStateCallback internalCallback =
+                    mInternalDownloadCallbacks.remove(callback);
+            if (internalCallback != null) {
+                internalCallback.stop();
+            }
+        }
+    }
+
+    /**
+     * Attempts to cancel the specified {@link DownloadRequest}.
+     *
+     * If the middleware is not aware of the specified download request,
+     * this method will throw an {@link IllegalArgumentException}.
+     *
+     * @param downloadRequest The download request that you wish to cancel.
+     */
+    public void cancelDownload(@NonNull DownloadRequest downloadRequest) {
+        IMbmsDownloadService downloadService = mService.get();
+        if (downloadService == null) {
+            throw new IllegalStateException("Middleware not yet bound");
+        }
+
+        try {
+            int result = downloadService.cancelDownload(downloadRequest);
+            if (result != MbmsErrors.SUCCESS) {
+                if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) {
+                    throw new IllegalArgumentException("Unknown download request.");
+                }
+                sendErrorToApp(result, null);
+                return;
+            }
+        } catch (RemoteException e) {
+            mService.set(null);
+            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
+            return;
+        }
+        deleteDownloadRequestToken(downloadRequest);
+    }
+
+    /**
+     * Gets information about the status of a file pending download.
+     *
+     * If there was a problem communicating with the middleware or if it has no records of the
+     * file indicated by {@code fileInfo} being associated with {@code downloadRequest},
+     * {@link #STATUS_UNKNOWN} will be returned.
+     *
+     * @param downloadRequest The download request to query.
+     * @param fileInfo The particular file within the request to get information on.
+     * @return The status of the download.
+     */
+    @DownloadStatus
+    public int getDownloadStatus(DownloadRequest downloadRequest, FileInfo fileInfo) {
+        IMbmsDownloadService downloadService = mService.get();
+        if (downloadService == null) {
+            throw new IllegalStateException("Middleware not yet bound");
+        }
+
+        try {
+            return downloadService.getDownloadStatus(downloadRequest, fileInfo);
+        } catch (RemoteException e) {
+            mService.set(null);
+            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
+            return STATUS_UNKNOWN;
+        }
+    }
+
+    /**
+     * Resets the middleware's knowledge of previously-downloaded files in this download request.
+     *
+     * Normally, the middleware keeps track of the hashes of downloaded files and won't re-download
+     * files whose server-reported hash matches one of the already-downloaded files. This means
+     * that if the file is accidentally deleted by the user or by the app, the middleware will
+     * not try to download it again.
+     * This method will reset the middleware's cache of hashes for the provided
+     * {@link DownloadRequest}, so that previously downloaded content will be downloaded again
+     * when available.
+     * This will not interrupt in-progress downloads.
+     *
+     * This is distinct from cancelling and re-issuing the download request -- if you cancel and
+     * re-issue, the middleware will not clear its cache of download state information.
+     *
+     * If the middleware is not aware of the specified download request, an
+     * {@link IllegalArgumentException} will be thrown.
+     *
+     * @param downloadRequest The request to re-download files for.
+     */
+    public void resetDownloadKnowledge(DownloadRequest downloadRequest) {
+        IMbmsDownloadService downloadService = mService.get();
+        if (downloadService == null) {
+            throw new IllegalStateException("Middleware not yet bound");
+        }
+
+        try {
+            int result = downloadService.resetDownloadKnowledge(downloadRequest);
+            if (result != MbmsErrors.SUCCESS) {
+                if (result == MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST) {
+                    throw new IllegalArgumentException("Unknown download request.");
+                }
+                sendErrorToApp(result, null);
+            }
+        } catch (RemoteException e) {
+            mService.set(null);
+            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
+        }
+    }
+
+    /**
+     * Terminates this instance.
+     *
+     * After this method returns,
+     * no further callbacks originating from the middleware will be enqueued on the provided
+     * instance of {@link MbmsDownloadSessionCallback}, but callbacks that have already been
+     * enqueued will still be delivered.
+     *
+     * It is safe to call {@link #create(Context, MbmsDownloadSessionCallback, int, Handler)} to
+     * obtain another instance of {@link MbmsDownloadSession} immediately after this method
+     * returns.
+     *
+     * May throw an {@link IllegalStateException}
+     */
+    @Override
+    public void close() {
+        try {
+            IMbmsDownloadService downloadService = mService.get();
+            if (downloadService == null) {
+                Log.i(LOG_TAG, "Service already dead");
+                return;
+            }
+            downloadService.dispose(mSubscriptionId);
+        } catch (RemoteException e) {
+            // Ignore
+            Log.i(LOG_TAG, "Remote exception while disposing of service");
+        } finally {
+            mService.set(null);
+            sIsInitialized.set(false);
+            mInternalCallback.stop();
+        }
+    }
+
+    private void writeDownloadRequestToken(DownloadRequest request) {
+        File token = getDownloadRequestTokenPath(request);
+        if (!token.getParentFile().exists()) {
+            token.getParentFile().mkdirs();
+        }
+        if (token.exists()) {
+            Log.w(LOG_TAG, "Download token " + token.getName() + " already exists");
+            return;
+        }
+        try {
+            if (!token.createNewFile()) {
+                throw new RuntimeException("Failed to create download token for request "
+                        + request);
+            }
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to create download token for request " + request
+                    + " due to IOException " + e);
+        }
+    }
+
+    private void deleteDownloadRequestToken(DownloadRequest request) {
+        File token = getDownloadRequestTokenPath(request);
+        if (!token.isFile()) {
+            Log.w(LOG_TAG, "Attempting to delete non-existent download token at " + token);
+            return;
+        }
+        if (!token.delete()) {
+            Log.w(LOG_TAG, "Couldn't delete download token at " + token);
+        }
+    }
+
+    private File getDownloadRequestTokenPath(DownloadRequest request) {
+        File tempFileLocation = MbmsUtils.getEmbmsTempFileDirForService(mContext,
+                request.getFileServiceId());
+        String downloadTokenFileName = request.getHash()
+                + MbmsDownloadReceiver.DOWNLOAD_TOKEN_SUFFIX;
+        return new File(tempFileLocation, downloadTokenFileName);
+    }
+
+    private void sendErrorToApp(int errorCode, String message) {
+        try {
+            mInternalCallback.onError(errorCode, message);
+        } catch (RemoteException e) {
+            // Ignore, should not happen locally.
+        }
+    }
+}
diff --git a/telephony/java/android/telephony/MbmsStreamingManager.java b/telephony/java/android/telephony/MbmsStreamingManager.java
deleted file mode 100644
index 911f83f..0000000
--- a/telephony/java/android/telephony/MbmsStreamingManager.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 2016 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.telephony;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.ServiceConnection;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.telephony.mbms.MbmsException;
-import android.telephony.mbms.MbmsStreamingManagerCallback;
-import android.telephony.mbms.MbmsUtils;
-import android.telephony.mbms.StreamingService;
-import android.telephony.mbms.StreamingServiceCallback;
-import android.telephony.mbms.StreamingServiceInfo;
-import android.telephony.mbms.vendor.IMbmsStreamingService;
-import android.util.Log;
-
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
-
-import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-
-/**
- * This class provides functionality for streaming media over MBMS.
- * @hide
- */
-public class MbmsStreamingManager {
-    private static final String LOG_TAG = "MbmsStreamingManager";
-    public static final String MBMS_STREAMING_SERVICE_ACTION =
-            "android.telephony.action.EmbmsStreaming";
-
-    private AtomicReference<IMbmsStreamingService> mService = new AtomicReference<>(null);
-    private MbmsStreamingManagerCallback mCallbackToApp;
-
-    private final Context mContext;
-    private int mSubscriptionId = INVALID_SUBSCRIPTION_ID;
-
-    /** @hide */
-    private MbmsStreamingManager(Context context, MbmsStreamingManagerCallback callback,
-                    int subscriptionId) {
-        mContext = context;
-        mCallbackToApp = callback;
-        mSubscriptionId = subscriptionId;
-    }
-
-    /**
-     * Create a new MbmsStreamingManager using the given subscription ID.
-     *
-     * Note that this call will bind a remote service. You may not call this method on your app's
-     * main thread. This may throw an {@link MbmsException}, indicating errors that may happen
-     * during the initialization or binding process.
-     *
-     * @param context The {@link Context} to use.
-     * @param callback A callback object on which you wish to receive results of asynchronous
-     *                 operations.
-     * @param subscriptionId The subscription ID to use.
-     */
-    public static MbmsStreamingManager create(Context context,
-            MbmsStreamingManagerCallback callback, int subscriptionId)
-            throws MbmsException {
-        MbmsStreamingManager manager = new MbmsStreamingManager(context, callback, subscriptionId);
-        manager.bindAndInitialize();
-        return manager;
-    }
-
-    /**
-     * Create a new MbmsStreamingManager using the system default data subscription ID.
-     * See {@link #create(Context, MbmsStreamingManagerCallback, int)}.
-     */
-    public static MbmsStreamingManager create(Context context,
-            MbmsStreamingManagerCallback callback)
-            throws MbmsException {
-        return create(context, callback, SubscriptionManager.getDefaultSubscriptionId());
-    }
-
-    /**
-     * Terminates this instance, ending calls to the registered listener.  Also terminates
-     * any streaming services spawned from this instance.
-     *
-     * May throw an {@link IllegalStateException}
-     */
-    public void dispose() {
-        IMbmsStreamingService streamingService = mService.get();
-        if (streamingService == null) {
-            // Ignore and return, assume already disposed.
-            return;
-        }
-        try {
-            streamingService.dispose(mSubscriptionId);
-        } catch (RemoteException e) {
-            // Ignore for now
-        }
-        mService.set(null);
-    }
-
-    /**
-     * An inspection API to retrieve the list of streaming media currently be advertised.
-     * The results are returned asynchronously through the previously registered callback.
-     * serviceClasses lets the app filter on types of programming and is opaque data between
-     * the app and the carrier.
-     *
-     * Multiple calls replace the list of serviceClasses of interest.
-     *
-     * This may throw an {@link MbmsException} containing any error in
-     * {@link android.telephony.mbms.MbmsException.GeneralErrors},
-     * {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND}, or
-     * {@link MbmsException#ERROR_MIDDLEWARE_LOST}.
-     *
-     * May also throw an unchecked {@link IllegalArgumentException} or an
-     * {@link IllegalStateException}
-     *
-     * @param classList A list of streaming service classes that the app would like updates on.
-     */
-    public void getStreamingServices(List<String> classList) throws MbmsException {
-        IMbmsStreamingService streamingService = mService.get();
-        if (streamingService == null) {
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
-        }
-        try {
-            int returnCode = streamingService.getStreamingServices(mSubscriptionId, classList);
-            if (returnCode != MbmsException.SUCCESS) {
-                throw new MbmsException(returnCode);
-            }
-        } catch (RemoteException e) {
-            Log.w(LOG_TAG, "Remote process died");
-            mService.set(null);
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
-        }
-    }
-
-    /**
-     * Starts streaming a requested service, reporting status to the indicated listener.
-     * Returns an object used to control that stream. The stream may not be ready for consumption
-     * immediately upon return from this method -- wait until the streaming state has been
-     * reported via
-     * {@link android.telephony.mbms.StreamingServiceCallback#streamStateUpdated(int, int)}
-     *
-     * May throw an
-     * {@link MbmsException} containing any of the error codes in
-     * {@link android.telephony.mbms.MbmsException.GeneralErrors},
-     * {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND}, or
-     * {@link MbmsException#ERROR_MIDDLEWARE_LOST}.
-     *
-     * May also throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
-     *
-     * Asynchronous errors through the listener include any of the errors in
-     * {@link android.telephony.mbms.MbmsException.GeneralErrors} or
-     * {@link android.telephony.mbms.MbmsException.StreamingErrors}.
-     *
-     * @param serviceInfo The information about the service to stream.
-     * @param listener A listener that'll be called when something about the stream changes.
-     * @return An instance of {@link StreamingService} through which the stream can be controlled.
-     */
-    public StreamingService startStreaming(StreamingServiceInfo serviceInfo,
-            StreamingServiceCallback listener) throws MbmsException {
-        IMbmsStreamingService streamingService = mService.get();
-        if (streamingService == null) {
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_NOT_BOUND);
-        }
-
-        try {
-            int returnCode = streamingService.startStreaming(
-                    mSubscriptionId, serviceInfo.getServiceId(), listener);
-            if (returnCode != MbmsException.SUCCESS) {
-                throw new MbmsException(returnCode);
-            }
-        } catch (RemoteException e) {
-            Log.w(LOG_TAG, "Remote process died");
-            mService.set(null);
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
-        }
-
-        return new StreamingService(mSubscriptionId, streamingService, serviceInfo, listener);
-    }
-
-    private void bindAndInitialize() throws MbmsException {
-        MbmsUtils.startBinding(mContext, MBMS_STREAMING_SERVICE_ACTION,
-                new ServiceConnection() {
-                    @Override
-                    public void onServiceConnected(ComponentName name, IBinder service) {
-                        IMbmsStreamingService streamingService =
-                                IMbmsStreamingService.Stub.asInterface(service);
-                        int result;
-                        try {
-                            result = streamingService.initialize(mCallbackToApp, mSubscriptionId);
-                        } catch (RemoteException e) {
-                            Log.e(LOG_TAG, "Service died before initialization");
-                            return;
-                        } catch (RuntimeException e) {
-                            Log.e(LOG_TAG, "Runtime exception during initialization");
-                            mCallbackToApp.error(
-                                    MbmsException.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
-                                    e.toString());
-                            return;
-                        }
-                        if (result != MbmsException.SUCCESS) {
-                            mCallbackToApp.error(result, "Error returned during initialization");
-                            return;
-                        }
-                        mService.set(streamingService);
-                    }
-
-                    @Override
-                    public void onServiceDisconnected(ComponentName name) {
-                        mService.set(null);
-                    }
-                });
-    }
-}
diff --git a/telephony/java/android/telephony/MbmsStreamingSession.java b/telephony/java/android/telephony/MbmsStreamingSession.java
new file mode 100644
index 0000000..efb6055
--- /dev/null
+++ b/telephony/java/android/telephony/MbmsStreamingSession.java
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2016 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.telephony;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.telephony.mbms.InternalStreamingSessionCallback;
+import android.telephony.mbms.InternalStreamingServiceCallback;
+import android.telephony.mbms.MbmsErrors;
+import android.telephony.mbms.MbmsStreamingSessionCallback;
+import android.telephony.mbms.MbmsUtils;
+import android.telephony.mbms.StreamingService;
+import android.telephony.mbms.StreamingServiceCallback;
+import android.telephony.mbms.StreamingServiceInfo;
+import android.telephony.mbms.vendor.IMbmsStreamingService;
+import android.util.ArraySet;
+import android.util.Log;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+/**
+ * This class provides functionality for streaming media over MBMS.
+ * @hide
+ */
+public class MbmsStreamingSession implements AutoCloseable {
+    private static final String LOG_TAG = "MbmsStreamingSession";
+
+    /**
+     * Service action which must be handled by the middleware implementing the MBMS streaming
+     * interface.
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String MBMS_STREAMING_SERVICE_ACTION =
+            "android.telephony.action.EmbmsStreaming";
+
+    private static AtomicBoolean sIsInitialized = new AtomicBoolean(false);
+
+    private AtomicReference<IMbmsStreamingService> mService = new AtomicReference<>(null);
+    private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
+        @Override
+        public void binderDied() {
+            sIsInitialized.set(false);
+            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, "Received death notification");
+        }
+    };
+
+    private InternalStreamingSessionCallback mInternalCallback;
+    private Set<StreamingService> mKnownActiveStreamingServices = new ArraySet<>();
+
+    private final Context mContext;
+    private int mSubscriptionId = INVALID_SUBSCRIPTION_ID;
+
+    /** @hide */
+    private MbmsStreamingSession(Context context, MbmsStreamingSessionCallback callback,
+                    int subscriptionId, Handler handler) {
+        mContext = context;
+        mSubscriptionId = subscriptionId;
+        if (handler == null) {
+            handler = new Handler(Looper.getMainLooper());
+        }
+        mInternalCallback = new InternalStreamingSessionCallback(callback, handler);
+    }
+
+    /**
+     * Create a new {@link MbmsStreamingSession} using the given subscription ID.
+     *
+     * Note that this call will bind a remote service. You may not call this method on your app's
+     * main thread.
+     *
+     * You may only have one instance of {@link MbmsStreamingSession} per UID. If you call this
+     * method while there is an active instance of {@link MbmsStreamingSession} in your process
+     * (in other words, one that has not had {@link #close()} called on it), this method will
+     * throw an {@link IllegalStateException}. If you call this method in a different process
+     * running under the same UID, an error will be indicated via
+     * {@link MbmsStreamingSessionCallback#onError(int, String)}.
+     *
+     * Note that initialization may fail asynchronously. If you wish to try again after you
+     * receive such an asynchronous error, you must call {@link #close()} on the instance of
+     * {@link MbmsStreamingSession} that you received before calling this method again.
+     *
+     * @param context The {@link Context} to use.
+     * @param callback A callback object on which you wish to receive results of asynchronous
+     *                 operations.
+     * @param subscriptionId The subscription ID to use.
+     * @param handler The handler you wish to receive callbacks on.
+     * @return An instance of {@link MbmsStreamingSession}, or null if an error occurred.
+     */
+    public static @Nullable MbmsStreamingSession create(@NonNull Context context,
+            final @NonNull MbmsStreamingSessionCallback callback, int subscriptionId,
+            @NonNull Handler handler) {
+        if (!sIsInitialized.compareAndSet(false, true)) {
+            throw new IllegalStateException("Cannot create two instances of MbmsStreamingSession");
+        }
+        MbmsStreamingSession session = new MbmsStreamingSession(context, callback,
+                subscriptionId, handler);
+
+        final int result = session.bindAndInitialize();
+        if (result != MbmsErrors.SUCCESS) {
+            sIsInitialized.set(false);
+            handler.post(new Runnable() {
+                @Override
+                public void run() {
+                    callback.onError(result, null);
+                }
+            });
+            return null;
+        }
+        return session;
+    }
+
+    /**
+     * Create a new {@link MbmsStreamingSession} using the system default data subscription ID.
+     * See {@link #create(Context, MbmsStreamingSessionCallback, int, Handler)}.
+     */
+    public static MbmsStreamingSession create(@NonNull Context context,
+            @NonNull MbmsStreamingSessionCallback callback, @NonNull Handler handler) {
+        return create(context, callback, SubscriptionManager.getDefaultSubscriptionId(), handler);
+    }
+
+    /**
+     * Terminates this instance. Also terminates
+     * any streaming services spawned from this instance as if
+     * {@link StreamingService#stopStreaming()} had been called on them. After this method returns,
+     * no further callbacks originating from the middleware will be enqueued on the provided
+     * instance of {@link MbmsStreamingSessionCallback}, but callbacks that have already been
+     * enqueued will still be delivered.
+     *
+     * It is safe to call {@link #create(Context, MbmsStreamingSessionCallback, int, Handler)} to
+     * obtain another instance of {@link MbmsStreamingSession} immediately after this method
+     * returns.
+     *
+     * May throw an {@link IllegalStateException}
+     */
+    public void close() {
+        try {
+            IMbmsStreamingService streamingService = mService.get();
+            if (streamingService == null) {
+                // Ignore and return, assume already disposed.
+                return;
+            }
+            streamingService.dispose(mSubscriptionId);
+            for (StreamingService s : mKnownActiveStreamingServices) {
+                s.getCallback().stop();
+            }
+            mKnownActiveStreamingServices.clear();
+        } catch (RemoteException e) {
+            // Ignore for now
+        } finally {
+            mService.set(null);
+            sIsInitialized.set(false);
+            mInternalCallback.stop();
+        }
+    }
+
+    /**
+     * An inspection API to retrieve the list of streaming media currently be advertised.
+     * The results are returned asynchronously via
+     * {@link MbmsStreamingSessionCallback#onStreamingServicesUpdated(List)} on the callback
+     * provided upon creation.
+     *
+     * Multiple calls replace the list of service classes of interest.
+     *
+     * May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}.
+     *
+     * @param serviceClassList A list of streaming service classes that the app would like updates
+     *                         on. The exact names of these classes should be negotiated with the
+     *                         wireless carrier separately.
+     */
+    public void requestUpdateStreamingServices(List<String> serviceClassList) {
+        IMbmsStreamingService streamingService = mService.get();
+        if (streamingService == null) {
+            throw new IllegalStateException("Middleware not yet bound");
+        }
+        try {
+            int returnCode = streamingService.requestUpdateStreamingServices(
+                    mSubscriptionId, serviceClassList);
+            if (returnCode != MbmsErrors.SUCCESS) {
+                sendErrorToApp(returnCode, null);
+            }
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "Remote process died");
+            mService.set(null);
+            sIsInitialized.set(false);
+            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
+        }
+    }
+
+    /**
+     * Starts streaming a requested service, reporting status to the indicated callback.
+     * Returns an object used to control that stream. The stream may not be ready for consumption
+     * immediately upon return from this method -- wait until the streaming state has been
+     * reported via
+     * {@link android.telephony.mbms.StreamingServiceCallback#onStreamStateUpdated(int, int)}
+     *
+     * May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
+     *
+     * Asynchronous errors through the callback include any of the errors in
+     * {@link MbmsErrors.GeneralErrors} or
+     * {@link MbmsErrors.StreamingErrors}.
+     *
+     * @param serviceInfo The information about the service to stream.
+     * @param callback A callback that'll be called when something about the stream changes.
+     * @param handler A handler that calls to {@code callback} should be called on.
+     * @return An instance of {@link StreamingService} through which the stream can be controlled.
+     *         May be {@code null} if an error occurred.
+     */
+    public @Nullable StreamingService startStreaming(StreamingServiceInfo serviceInfo,
+            StreamingServiceCallback callback, @NonNull Handler handler) {
+        IMbmsStreamingService streamingService = mService.get();
+        if (streamingService == null) {
+            throw new IllegalStateException("Middleware not yet bound");
+        }
+
+        InternalStreamingServiceCallback serviceCallback = new InternalStreamingServiceCallback(
+                callback, handler);
+
+        StreamingService serviceForApp = new StreamingService(
+                mSubscriptionId, streamingService, this, serviceInfo, serviceCallback);
+        mKnownActiveStreamingServices.add(serviceForApp);
+
+        try {
+            int returnCode = streamingService.startStreaming(
+                    mSubscriptionId, serviceInfo.getServiceId(), serviceCallback);
+            if (returnCode != MbmsErrors.SUCCESS) {
+                sendErrorToApp(returnCode, null);
+                return null;
+            }
+        } catch (RemoteException e) {
+            Log.w(LOG_TAG, "Remote process died");
+            mService.set(null);
+            sIsInitialized.set(false);
+            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
+            return null;
+        }
+
+        return serviceForApp;
+    }
+
+    /** @hide */
+    public void onStreamingServiceStopped(StreamingService service) {
+        mKnownActiveStreamingServices.remove(service);
+    }
+
+    private int bindAndInitialize() {
+        return MbmsUtils.startBinding(mContext, MBMS_STREAMING_SERVICE_ACTION,
+                new ServiceConnection() {
+                    @Override
+                    public void onServiceConnected(ComponentName name, IBinder service) {
+                        IMbmsStreamingService streamingService =
+                                IMbmsStreamingService.Stub.asInterface(service);
+                        int result;
+                        try {
+                            result = streamingService.initialize(mInternalCallback,
+                                    mSubscriptionId);
+                        } catch (RemoteException e) {
+                            Log.e(LOG_TAG, "Service died before initialization");
+                            sendErrorToApp(
+                                    MbmsErrors.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
+                                    e.toString());
+                            sIsInitialized.set(false);
+                            return;
+                        } catch (RuntimeException e) {
+                            Log.e(LOG_TAG, "Runtime exception during initialization");
+                            sendErrorToApp(
+                                    MbmsErrors.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
+                                    e.toString());
+                            sIsInitialized.set(false);
+                            return;
+                        }
+                        if (result != MbmsErrors.SUCCESS) {
+                            sendErrorToApp(result, "Error returned during initialization");
+                            sIsInitialized.set(false);
+                            return;
+                        }
+                        try {
+                            streamingService.asBinder().linkToDeath(mDeathRecipient, 0);
+                        } catch (RemoteException e) {
+                            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST,
+                                    "Middleware lost during initialization");
+                            sIsInitialized.set(false);
+                            return;
+                        }
+                        mService.set(streamingService);
+                    }
+
+                    @Override
+                    public void onServiceDisconnected(ComponentName name) {
+                        sIsInitialized.set(false);
+                        mService.set(null);
+                    }
+                });
+    }
+
+    private void sendErrorToApp(int errorCode, String message) {
+        try {
+            mInternalCallback.onError(errorCode, message);
+        } catch (RemoteException e) {
+            // Ignore, should not happen locally.
+        }
+    }
+}
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 8705446..d5ff1ad 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -2540,11 +2540,11 @@
     }
 
     // Split a phone number like "+20(123)-456#" using spaces, ignoring anything that is not
-    // a digit, to produce a result like "20 123 456".
+    // a digit or the characters * and #, to produce a result like "20 123 456#".
     private static String splitAtNonNumerics(CharSequence number) {
         StringBuilder sb = new StringBuilder(number.length());
         for (int i = 0; i < number.length(); i++) {
-            sb.append(PhoneNumberUtils.isISODigit(number.charAt(i))
+            sb.append(PhoneNumberUtils.is12Key(number.charAt(i))
                     ? number.charAt(i)
                     : " ");
         }
diff --git a/telephony/java/android/telephony/mbms/DownloadProgressListener.java b/telephony/java/android/telephony/mbms/DownloadProgressListener.java
deleted file mode 100644
index d6bd5dc..0000000
--- a/telephony/java/android/telephony/mbms/DownloadProgressListener.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2016 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.telephony.mbms;
-
-/**
- * A optional listener class used by download clients to track progress.
- * @hide
- */
-public class DownloadProgressListener extends IDownloadProgressListener.Stub {
-    /**
-     * Gives process callbacks for a given DownloadRequest.
-     * This is optionally specified when requesting a download and
-     * only lives while the app is running - it's unlikely to be useful for
-     * downloads far in the future.
-     *
-     * @param request a {@link DownloadRequest}, indicating which download is being referenced.
-     * @param fileInfo a {@link FileInfo} specifying the file to report progress on.  Note that
-     *   the request may result in many files being downloaded and the client
-     *   may not have been able to get a list of them in advance.
-     * @param currentDownloadSize is the current amount downloaded.
-     * @param fullDownloadSize is the total number of bytes that make up the downloaded content.
-     *   This may be different from the decoded final size, but is useful in gauging download
-     *   progress.
-     * @param currentDecodedSize is the number of bytes that have been decoded.
-     * @param fullDecodedSize is the total number of bytes that make up the final decoded content.
-     */
-    public void progress(DownloadRequest request, FileInfo fileInfo,
-            int currentDownloadSize, int fullDownloadSize,
-            int currentDecodedSize, int fullDecodedSize) {
-    }
-}
diff --git a/telephony/java/android/telephony/mbms/DownloadRequest.java b/telephony/java/android/telephony/mbms/DownloadRequest.java
index 01e0bbd..a5f256e 100644
--- a/telephony/java/android/telephony/mbms/DownloadRequest.java
+++ b/telephony/java/android/telephony/mbms/DownloadRequest.java
@@ -16,6 +16,7 @@
 
 package android.telephony.mbms;
 
+import android.annotation.SystemApi;
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Parcel;
@@ -25,6 +26,7 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.io.File;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
@@ -36,34 +38,28 @@
 import java.util.Objects;
 
 /**
- * A Parcelable class describing a pending Cell-Broadcast download request
+ * Describes a request to download files over cell-broadcast. Instances of this class should be
+ * created by the app when requesting a download, and instances of this class will be passed back
+ * to the app when the middleware updates the status of the download.
  * @hide
  */
-public class DownloadRequest implements Parcelable {
+public final class DownloadRequest implements Parcelable {
     // Version code used to keep token calculation consistent.
     private static final int CURRENT_VERSION = 1;
     private static final String LOG_TAG = "MbmsDownloadRequest";
 
-    /**
-     * Maximum permissible length for the app's download-completion intent, when serialized via
-     * {@link Intent#toUri(int)}.
-     */
+    /** @hide */
     public static final int MAX_APP_INTENT_SIZE = 50000;
 
-    /**
-     * Maximum permissible length for the app's destination path, when serialized via
-     * {@link Uri#toString()}.
-     */
+    /** @hide */
     public static final int MAX_DESTINATION_URI_SIZE = 50000;
 
     /** @hide */
     private static class OpaqueDataContainer implements Serializable {
-        private final String destinationUri;
         private final String appIntent;
         private final int version;
 
-        public OpaqueDataContainer(String destinationUri, String appIntent, int version) {
-            this.destinationUri = destinationUri;
+        public OpaqueDataContainer(String appIntent, int version) {
             this.appIntent = appIntent;
             this.version = version;
         }
@@ -72,44 +68,56 @@
     public static class Builder {
         private String fileServiceId;
         private Uri source;
-        private Uri dest;
         private int subscriptionId;
         private String appIntent;
         private int version = CURRENT_VERSION;
 
+        /**
+         * Sets the service from which the download request to be built will download from.
+         * @param serviceInfo
+         * @return
+         */
         public Builder setServiceInfo(FileServiceInfo serviceInfo) {
             fileServiceId = serviceInfo.getServiceId();
             return this;
         }
 
         /**
+         * Set the service ID for the download request. For use by the middleware only.
          * @hide
-         * TODO: systemapi
          */
+        //@SystemApi
         public Builder setServiceId(String serviceId) {
             fileServiceId = serviceId;
             return this;
         }
 
+        /**
+         * Sets the source URI for the download request to be built.
+         * @param source
+         */
         public Builder setSource(Uri source) {
             this.source = source;
             return this;
         }
 
-        public Builder setDest(Uri dest) {
-            if (dest.toString().length() > MAX_DESTINATION_URI_SIZE) {
-                throw new IllegalArgumentException("Destination uri must not exceed length " +
-                        MAX_DESTINATION_URI_SIZE);
-            }
-            this.dest = dest;
+        /**
+         * Set the subscription ID on which the file(s) should be downloaded.
+         * @param subscriptionId
+         */
+        public Builder setSubscriptionId(int subscriptionId) {
+            this.subscriptionId = subscriptionId;
             return this;
         }
 
-        public Builder setSubscriptionId(int sub) {
-            this.subscriptionId = sub;
-            return this;
-        }
-
+        /**
+         * Set the {@link Intent} that should be sent when the download completes or fails. This
+         * should be an intent with a explicit {@link android.content.ComponentName} targeted to a
+         * {@link android.content.BroadcastReceiver} in the app's package.
+         *
+         * The middleware should not use this method.
+         * @param intent
+         */
         public Builder setAppIntent(Intent intent) {
             this.appIntent = intent.toUri(0);
             if (this.appIntent.length() > MAX_APP_INTENT_SIZE) {
@@ -120,17 +128,20 @@
         }
 
         /**
-         * For use by middleware only
-         * TODO: systemapi
+         * For use by the middleware to set the byte array of opaque data. The opaque data
+         * includes information about the download request that is used by the client app and the
+         * manager code, but is irrelevant to the middleware.
+         * @param data A byte array, the contents of which should have been originally obtained
+         *             from {@link DownloadRequest#getOpaqueData()}.
          * @hide
          */
+        //@SystemApi
         public Builder setOpaqueData(byte[] data) {
             try {
                 ObjectInputStream stream = new ObjectInputStream(new ByteArrayInputStream(data));
                 OpaqueDataContainer dataContainer = (OpaqueDataContainer) stream.readObject();
                 version = dataContainer.version;
                 appIntent = dataContainer.appIntent;
-                dest = Uri.parse(dataContainer.destinationUri);
             } catch (IOException e) {
                 // Really should never happen
                 Log.e(LOG_TAG, "Got IOException trying to parse opaque data");
@@ -143,24 +154,21 @@
         }
 
         public DownloadRequest build() {
-            return new DownloadRequest(fileServiceId, source, dest,
-                    subscriptionId, appIntent, version);
+            return new DownloadRequest(fileServiceId, source, subscriptionId, appIntent, version);
         }
     }
 
     private final String fileServiceId;
     private final Uri sourceUri;
-    private final Uri destinationUri;
     private final int subscriptionId;
     private final String serializedResultIntentForApp;
     private final int version;
 
     private DownloadRequest(String fileServiceId,
-            Uri source, Uri dest,
-            int sub, String appIntent, int version) {
+            Uri source, int sub,
+            String appIntent, int version) {
         this.fileServiceId = fileServiceId;
         sourceUri = source;
-        destinationUri = dest;
         subscriptionId = sub;
         serializedResultIntentForApp = appIntent;
         this.version = version;
@@ -173,7 +181,6 @@
     private DownloadRequest(DownloadRequest dr) {
         fileServiceId = dr.fileServiceId;
         sourceUri = dr.sourceUri;
-        destinationUri = dr.destinationUri;
         subscriptionId = dr.subscriptionId;
         serializedResultIntentForApp = dr.serializedResultIntentForApp;
         version = dr.version;
@@ -182,7 +189,6 @@
     private DownloadRequest(Parcel in) {
         fileServiceId = in.readString();
         sourceUri = in.readParcelable(getClass().getClassLoader());
-        destinationUri = in.readParcelable(getClass().getClassLoader());
         subscriptionId = in.readInt();
         serializedResultIntentForApp = in.readString();
         version = in.readInt();
@@ -195,28 +201,37 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeString(fileServiceId);
         out.writeParcelable(sourceUri, flags);
-        out.writeParcelable(destinationUri, flags);
         out.writeInt(subscriptionId);
         out.writeString(serializedResultIntentForApp);
         out.writeInt(version);
     }
 
+    /**
+     * @return The ID of the file service to download from.
+     */
     public String getFileServiceId() {
         return fileServiceId;
     }
 
+    /**
+     * @return The source URI to download from
+     */
     public Uri getSourceUri() {
         return sourceUri;
     }
 
-    public Uri getDestinationUri() {
-        return destinationUri;
-    }
-
+    /**
+     * @return The subscription ID on which to perform MBMS operations.
+     */
     public int getSubscriptionId() {
         return subscriptionId;
     }
 
+    /**
+     * For internal use -- returns the intent to send to the app after download completion or
+     * failure.
+     * @hide
+     */
     public Intent getIntentForApp() {
         try {
             return Intent.parseUri(serializedResultIntentForApp, 0);
@@ -226,15 +241,19 @@
     }
 
     /**
+     * For use by the middleware only. The byte array returned from this method should be
+     * persisted and sent back to the app upon download completion or failure by passing it into
+     * {@link Builder#setOpaqueData(byte[])}.
+     * @return A byte array of opaque data to persist.
      * @hide
-     * TODO: systemapi
      */
+    //@SystemApi
     public byte[] getOpaqueData() {
         try {
             ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
             ObjectOutputStream stream = new ObjectOutputStream(byteArrayOutputStream);
             OpaqueDataContainer container = new OpaqueDataContainer(
-                    destinationUri.toString(), serializedResultIntentForApp, version);
+                    serializedResultIntentForApp, version);
             stream.writeObject(container);
             stream.flush();
             return byteArrayOutputStream.toByteArray();
@@ -261,6 +280,22 @@
     };
 
     /**
+     * Maximum permissible length for the app's destination path, when serialized via
+     * {@link Uri#toString()}.
+     */
+    public static int getMaxAppIntentSize() {
+        return MAX_APP_INTENT_SIZE;
+    }
+
+    /**
+     * Maximum permissible length for the app's download-completion intent, when serialized via
+     * {@link Intent#toUri(int)}.
+     */
+    public static int getMaxDestinationUriSize() {
+        return MAX_DESTINATION_URI_SIZE;
+    }
+
+    /**
      * @hide
      */
     public boolean isMultipartDownload() {
@@ -284,7 +319,6 @@
         if (version >= 1) {
             // Hash the source URI, destination URI, and the app intent
             digest.update(sourceUri.toString().getBytes(StandardCharsets.UTF_8));
-            digest.update(destinationUri.toString().getBytes(StandardCharsets.UTF_8));
             digest.update(serializedResultIntentForApp.getBytes(StandardCharsets.UTF_8));
         }
         // Add updates for future versions here
@@ -305,13 +339,12 @@
                 version == request.version &&
                 Objects.equals(fileServiceId, request.fileServiceId) &&
                 Objects.equals(sourceUri, request.sourceUri) &&
-                Objects.equals(destinationUri, request.destinationUri) &&
                 Objects.equals(serializedResultIntentForApp, request.serializedResultIntentForApp);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(fileServiceId, sourceUri, destinationUri,
+        return Objects.hash(fileServiceId, sourceUri,
                 subscriptionId, serializedResultIntentForApp, version);
     }
 }
diff --git a/telephony/java/android/telephony/mbms/DownloadStateCallback.java b/telephony/java/android/telephony/mbms/DownloadStateCallback.java
new file mode 100644
index 0000000..26d6879
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/DownloadStateCallback.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 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.telephony.mbms;
+
+import android.telephony.MbmsDownloadSession;
+
+/**
+ * A optional listener class used by download clients to track progress. Apps should extend this
+ * class and pass an instance into
+ * {@link MbmsDownloadSession#download(DownloadRequest)}
+ *
+ * This is optionally specified when requesting a download and will only be called while the app
+ * is running.
+ * @hide
+ */
+public class DownloadStateCallback {
+
+    /**
+     * Called when the middleware wants to report progress for a file in a {@link DownloadRequest}.
+     *
+     * @param request a {@link DownloadRequest}, indicating which download is being referenced.
+     * @param fileInfo a {@link FileInfo} specifying the file to report progress on.  Note that
+     *   the request may result in many files being downloaded and the client
+     *   may not have been able to get a list of them in advance.
+     * @param currentDownloadSize is the current amount downloaded.
+     * @param fullDownloadSize is the total number of bytes that make up the downloaded content.
+     *   This may be different from the decoded final size, but is useful in gauging download
+     *   progress.
+     * @param currentDecodedSize is the number of bytes that have been decoded.
+     * @param fullDecodedSize is the total number of bytes that make up the final decoded content.
+     */
+    public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo,
+            int currentDownloadSize, int fullDownloadSize,
+            int currentDecodedSize, int fullDecodedSize) {
+    }
+
+    /**
+     * Gives download state callbacks for a file in a {@link DownloadRequest}.
+     *
+     * @param request a {@link DownloadRequest}, indicating which download is being referenced.
+     * @param fileInfo a {@link FileInfo} specifying the file to report progress on.  Note that
+     *   the request may result in many files being downloaded and the client
+     *   may not have been able to get a list of them in advance.
+     * @param state The current state of the download.
+     */
+    public void onStateUpdated(DownloadRequest request, FileInfo fileInfo,
+            @MbmsDownloadSession.DownloadStatus int state) {
+    }
+}
diff --git a/telephony/java/android/telephony/mbms/FileInfo.java b/telephony/java/android/telephony/mbms/FileInfo.java
index 1b87393..bfa99e3 100644
--- a/telephony/java/android/telephony/mbms/FileInfo.java
+++ b/telephony/java/android/telephony/mbms/FileInfo.java
@@ -16,38 +16,21 @@
 
 package android.telephony.mbms;
 
+import android.annotation.SystemApi;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 /**
- * A Parcelable class Cell-Broadcast downloadable file information.
+ * Describes a single file that is available over MBMS.
  * @hide
  */
-public class FileInfo implements Parcelable {
+public final class FileInfo implements Parcelable {
 
-    /**
-     * The URI into the carriers infrastructure which points to this file.
-     * This is used internally but is also one of the few pieces of data about the content that is
-     * exposed and may be needed for disambiguation by the application.
-     */
     private final Uri uri;
 
-    /**
-     * The mime type of the content.
-     */
     private final String mimeType;
 
-    /**
-     * The size of the file in bytes.
-     */
-    private final long size;
-
-    /**
-     * The MD5 hash of the file.
-     */
-    private final byte md5Hash[];
-
     public static final Parcelable.Creator<FileInfo> CREATOR =
             new Parcelable.Creator<FileInfo>() {
         @Override
@@ -61,29 +44,24 @@
         }
     };
 
-    public FileInfo(Uri uri, String mimeType, long size, byte[] md5Hash) {
+    /**
+     * @hide
+     */
+    //@SystemApi
+    public FileInfo(Uri uri, String mimeType) {
         this.uri = uri;
         this.mimeType = mimeType;
-        this.size = size;
-        this.md5Hash = md5Hash;
     }
 
     private FileInfo(Parcel in) {
         uri = in.readParcelable(null);
         mimeType = in.readString();
-        size = in.readLong();
-        int arraySize = in.readInt();
-        md5Hash = new byte[arraySize];
-        in.readByteArray(md5Hash);
     }
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeParcelable(uri, flags);
         dest.writeString(mimeType);
-        dest.writeLong(size);
-        dest.writeInt(md5Hash.length);
-        dest.writeByteArray(md5Hash);
     }
 
     @Override
@@ -91,19 +69,18 @@
         return 0;
     }
 
+    /**
+     * @return The URI in the carrier's infrastructure which points to this file. Apps should
+     * negotiate the contents of this URI separately with the carrier.
+     */
     public Uri getUri() {
         return uri;
     }
 
+    /**
+     * @return The MIME type of the file.
+     */
     public String getMimeType() {
         return mimeType;
     }
-
-    public long getSize() {
-        return size;
-    }
-
-    public byte[] getMd5Hash() {
-        return md5Hash;
-    }
 }
diff --git a/telephony/java/android/telephony/mbms/FileServiceInfo.java b/telephony/java/android/telephony/mbms/FileServiceInfo.java
index 6646dc8..51e20a3 100644
--- a/telephony/java/android/telephony/mbms/FileServiceInfo.java
+++ b/telephony/java/android/telephony/mbms/FileServiceInfo.java
@@ -16,6 +16,7 @@
 
 package android.telephony.mbms;
 
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -26,12 +27,15 @@
 import java.util.Map;
 
 /**
- * A Parcelable class Cell-Broadcast downloadable file information.
+ * Describes a file service available from the carrier from which files can be downloaded via
+ * cell-broadcast.
  * @hide
  */
-public class FileServiceInfo extends ServiceInfo implements Parcelable {
+public final class FileServiceInfo extends ServiceInfo implements Parcelable {
     private final List<FileInfo> files;
 
+    /** @hide */
+    //@SystemApi
     public FileServiceInfo(Map<Locale, String> newNames, String newClassName,
             List<Locale> newLocales, String newServiceId, Date start, Date end,
             List<FileInfo> newFiles) {
@@ -55,7 +59,7 @@
     FileServiceInfo(Parcel in) {
         super(in);
         files = new ArrayList<FileInfo>();
-        in.readList(files, null);
+        in.readList(files, FileInfo.class.getClassLoader());
     }
 
     @Override
@@ -69,8 +73,12 @@
         return 0;
     }
 
+    /**
+     * @return A list of files available from this service. Note that this list may not be
+     * exhaustive -- the middleware may not have information on all files that are available.
+     * Consult the carrier for an authoritative and exhaustive list.
+     */
     public List<FileInfo> getFiles() {
         return files;
     }
-
 }
diff --git a/telephony/java/android/telephony/mbms/IDownloadProgressListener.aidl b/telephony/java/android/telephony/mbms/IDownloadStateCallback.aidl
similarity index 75%
rename from telephony/java/android/telephony/mbms/IDownloadProgressListener.aidl
rename to telephony/java/android/telephony/mbms/IDownloadStateCallback.aidl
index bb9dc6c..cebc70d 100755
--- a/telephony/java/android/telephony/mbms/IDownloadProgressListener.aidl
+++ b/telephony/java/android/telephony/mbms/IDownloadStateCallback.aidl
@@ -23,12 +23,15 @@
  * The optional interface used by download clients to track progress.
  * @hide
  */
-interface IDownloadProgressListener
+interface IDownloadStateCallback
 {
     /**
      * Gives progress callbacks for a given DownloadRequest.  Includes a FileInfo
      * as the list of files may not have been known at request-time.
      */
-    void progress(in DownloadRequest request, in FileInfo fileInfo, int currentDownloadSize,
-            int fullDownloadSize, int currentDecodedSize, int fullDecodedSize);
+    void onProgressUpdated(in DownloadRequest request, in FileInfo fileInfo,
+            int currentDownloadSize, int fullDownloadSize,
+            int currentDecodedSize, int fullDecodedSize);
+
+    void onStateUpdated(in DownloadRequest request, in FileInfo fileInfo, int state);
 }
diff --git a/telephony/java/android/telephony/mbms/IMbmsDownloadManagerCallback.aidl b/telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl
similarity index 80%
rename from telephony/java/android/telephony/mbms/IMbmsDownloadManagerCallback.aidl
rename to telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl
index ac2f202..0d813a7 100755
--- a/telephony/java/android/telephony/mbms/IMbmsDownloadManagerCallback.aidl
+++ b/telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl
@@ -24,11 +24,11 @@
  * The interface the clients top-level file download listener will satisfy.
  * @hide
  */
-oneway interface IMbmsDownloadManagerCallback
+oneway interface IMbmsDownloadSessionCallback
 {
-    void error(int errorCode, String message);
+    void onError(int errorCode, String message);
 
-    void fileServicesUpdated(in List<FileServiceInfo> services);
+    void onFileServicesUpdated(in List<FileServiceInfo> services);
 
-    void middlewareReady();
+    void onMiddlewareReady();
 }
diff --git a/telephony/java/android/telephony/mbms/IMbmsStreamingManagerCallback.aidl b/telephony/java/android/telephony/mbms/IMbmsStreamingSessionCallback.aidl
similarity index 80%
rename from telephony/java/android/telephony/mbms/IMbmsStreamingManagerCallback.aidl
rename to telephony/java/android/telephony/mbms/IMbmsStreamingSessionCallback.aidl
index 007aee7..0bf0ebc 100755
--- a/telephony/java/android/telephony/mbms/IMbmsStreamingManagerCallback.aidl
+++ b/telephony/java/android/telephony/mbms/IMbmsStreamingSessionCallback.aidl
@@ -24,11 +24,11 @@
  * The interface the clients top-level streaming listener will satisfy.
  * @hide
  */
-oneway interface IMbmsStreamingManagerCallback
+oneway interface IMbmsStreamingSessionCallback
 {
-    void error(int errorCode, String message);
+    void onError(int errorCode, String message);
 
-    void streamingServicesUpdated(in List<StreamingServiceInfo> services);
+    void onStreamingServicesUpdated(in List<StreamingServiceInfo> services);
 
-    void middlewareReady();
+    void onMiddlewareReady();
 }
diff --git a/telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl b/telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl
index 0952fbe..164cefb 100755
--- a/telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl
+++ b/telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl
@@ -20,9 +20,9 @@
  * @hide
  */
 oneway interface IStreamingServiceCallback {
-    void error(int errorCode, String message);
-    void streamStateUpdated(int state, int reason);
-    void mediaDescriptionUpdated();
-    void broadcastSignalStrengthUpdated(int signalStrength);
-    void streamMethodUpdated(int methodType);
+    void onError(int errorCode, String message);
+    void onStreamStateUpdated(int state, int reason);
+    void onMediaDescriptionUpdated();
+    void onBroadcastSignalStrengthUpdated(int signalStrength);
+    void onStreamMethodUpdated(int methodType);
 }
diff --git a/telephony/java/android/telephony/mbms/InternalDownloadSessionCallback.java b/telephony/java/android/telephony/mbms/InternalDownloadSessionCallback.java
new file mode 100644
index 0000000..a7a5958
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/InternalDownloadSessionCallback.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2017 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.telephony.mbms;
+
+import android.os.Handler;
+import android.os.RemoteException;
+
+import java.util.List;
+
+/** @hide */
+public class InternalDownloadSessionCallback extends IMbmsDownloadSessionCallback.Stub {
+
+    private final Handler mHandler;
+    private final MbmsDownloadSessionCallback mAppCallback;
+    private volatile boolean mIsStopped = false;
+
+    public InternalDownloadSessionCallback(MbmsDownloadSessionCallback appCallback,
+            Handler handler) {
+        mAppCallback = appCallback;
+        mHandler = handler;
+    }
+
+    @Override
+    public void onError(final int errorCode, final String message) throws RemoteException {
+        if (mIsStopped) {
+            return;
+        }
+
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mAppCallback.onError(errorCode, message);
+            }
+        });
+    }
+
+    @Override
+    public void onFileServicesUpdated(final List<FileServiceInfo> services) throws RemoteException {
+        if (mIsStopped) {
+            return;
+        }
+
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mAppCallback.onFileServicesUpdated(services);
+            }
+        });
+    }
+
+    @Override
+    public void onMiddlewareReady() throws RemoteException {
+        if (mIsStopped) {
+            return;
+        }
+
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mAppCallback.onMiddlewareReady();
+            }
+        });
+    }
+
+    public Handler getHandler() {
+        return mHandler;
+    }
+
+    public void stop() {
+        mIsStopped = true;
+    }
+}
diff --git a/telephony/java/android/telephony/mbms/InternalDownloadStateCallback.java b/telephony/java/android/telephony/mbms/InternalDownloadStateCallback.java
new file mode 100644
index 0000000..8702952
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/InternalDownloadStateCallback.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 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.telephony.mbms;
+
+import android.os.Handler;
+import android.os.RemoteException;
+
+/**
+ * @hide
+ */
+public class InternalDownloadStateCallback extends IDownloadStateCallback.Stub {
+    private final Handler mHandler;
+    private final DownloadStateCallback mAppCallback;
+    private volatile boolean mIsStopped = false;
+
+    public InternalDownloadStateCallback(DownloadStateCallback appCallback, Handler handler) {
+        mAppCallback = appCallback;
+        mHandler = handler;
+    }
+
+    @Override
+    public void onProgressUpdated(final DownloadRequest request, final FileInfo fileInfo,
+            final int currentDownloadSize, final int fullDownloadSize, final int currentDecodedSize,
+            final int fullDecodedSize) throws RemoteException {
+        if (mIsStopped) {
+            return;
+        }
+
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mAppCallback.onProgressUpdated(request, fileInfo, currentDownloadSize,
+                        fullDownloadSize, currentDecodedSize, fullDecodedSize);
+            }
+        });
+    }
+
+    @Override
+    public void onStateUpdated(final DownloadRequest request, final FileInfo fileInfo,
+            final int state) throws RemoteException {
+        if (mIsStopped) {
+            return;
+        }
+
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mAppCallback.onStateUpdated(request, fileInfo, state);
+            }
+        });
+    }
+
+    public void stop() {
+        mIsStopped = true;
+    }
+}
diff --git a/telephony/java/android/telephony/mbms/InternalStreamingServiceCallback.java b/telephony/java/android/telephony/mbms/InternalStreamingServiceCallback.java
new file mode 100644
index 0000000..eb6579ce
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/InternalStreamingServiceCallback.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2017 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.telephony.mbms;
+
+import android.os.Handler;
+import android.os.RemoteException;
+
+/** @hide */
+public class InternalStreamingServiceCallback extends IStreamingServiceCallback.Stub {
+    private final StreamingServiceCallback mAppCallback;
+    private final Handler mHandler;
+    private volatile boolean mIsStopped = false;
+
+    public InternalStreamingServiceCallback(StreamingServiceCallback appCallback, Handler handler) {
+        mAppCallback = appCallback;
+        mHandler = handler;
+    }
+
+    @Override
+    public void onError(final int errorCode, final String message) throws RemoteException {
+        if (mIsStopped) {
+            return;
+        }
+
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mAppCallback.onError(errorCode, message);
+            }
+        });
+    }
+
+    @Override
+    public void onStreamStateUpdated(final int state, final int reason) throws RemoteException {
+        if (mIsStopped) {
+            return;
+        }
+
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mAppCallback.onStreamStateUpdated(state, reason);
+            }
+        });
+    }
+
+    @Override
+    public void onMediaDescriptionUpdated() throws RemoteException {
+        if (mIsStopped) {
+            return;
+        }
+
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mAppCallback.onMediaDescriptionUpdated();
+            }
+        });
+    }
+
+    @Override
+    public void onBroadcastSignalStrengthUpdated(final int signalStrength) throws RemoteException {
+        if (mIsStopped) {
+            return;
+        }
+
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mAppCallback.onBroadcastSignalStrengthUpdated(signalStrength);
+            }
+        });
+    }
+
+    @Override
+    public void onStreamMethodUpdated(final int methodType) throws RemoteException {
+        if (mIsStopped) {
+            return;
+        }
+
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mAppCallback.onStreamMethodUpdated(methodType);
+            }
+        });
+    }
+
+    public void stop() {
+        mIsStopped = true;
+    }
+}
diff --git a/telephony/java/android/telephony/mbms/InternalStreamingSessionCallback.java b/telephony/java/android/telephony/mbms/InternalStreamingSessionCallback.java
new file mode 100644
index 0000000..d782d12
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/InternalStreamingSessionCallback.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2017 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.telephony.mbms;
+
+import android.os.Handler;
+import android.os.RemoteException;
+
+import java.util.List;
+
+/** @hide */
+public class InternalStreamingSessionCallback extends IMbmsStreamingSessionCallback.Stub {
+    private final Handler mHandler;
+    private final MbmsStreamingSessionCallback mAppCallback;
+    private volatile boolean mIsStopped = false;
+
+    public InternalStreamingSessionCallback(MbmsStreamingSessionCallback appCallback,
+            Handler handler) {
+        mAppCallback = appCallback;
+        mHandler = handler;
+    }
+
+    @Override
+    public void onError(final int errorCode, final String message) throws RemoteException {
+        if (mIsStopped) {
+            return;
+        }
+
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mAppCallback.onError(errorCode, message);
+            }
+        });
+    }
+
+    @Override
+    public void onStreamingServicesUpdated(final List<StreamingServiceInfo> services)
+            throws RemoteException {
+        if (mIsStopped) {
+            return;
+        }
+
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mAppCallback.onStreamingServicesUpdated(services);
+            }
+        });
+    }
+
+    @Override
+    public void onMiddlewareReady() throws RemoteException {
+        if (mIsStopped) {
+            return;
+        }
+
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                mAppCallback.onMiddlewareReady();
+            }
+        });
+    }
+
+    public Handler getHandler() {
+        return mHandler;
+    }
+
+    public void stop() {
+        mIsStopped = true;
+    }
+}
diff --git a/telephony/java/android/telephony/mbms/MbmsDownloadManagerCallback.java b/telephony/java/android/telephony/mbms/MbmsDownloadManagerCallback.java
deleted file mode 100644
index ba25f66..0000000
--- a/telephony/java/android/telephony/mbms/MbmsDownloadManagerCallback.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2016 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.telephony.mbms;
-
-import java.util.List;
-
-/**
- * A Parcelable class with Cell-Broadcast service information.
- * @hide
- */
-public class MbmsDownloadManagerCallback extends IMbmsDownloadManagerCallback.Stub {
-
-    public final static int ERROR_CARRIER_NOT_SUPPORTED      = 1;
-    public final static int ERROR_UNABLE_TO_INITIALIZE       = 2;
-    public final static int ERROR_UNABLE_TO_ALLOCATE_MEMORY  = 3;
-
-
-    public void error(int errorCode, String message) {
-        // default implementation empty
-    }
-
-    /**
-     * Called to indicate published File Services have changed.
-     *
-     * This will only be called after the application has requested
-     * a list of file services and specified a service class list
-     * of interest AND the results of a subsequent getFileServices
-     * call with the same service class list would return different
-     * results.
-     *
-     * @param services a List of FileServiceInfos
-     *
-     */
-    public void fileServicesUpdated(List<FileServiceInfo> services) {
-        // default implementation empty
-    }
-
-    /**
-     * Called to indicate that the middleware has been initialized and is ready.
-     *
-     * Before this method is called, calling any method on an instance of
-     * {@link android.telephony.MbmsDownloadManager} will result in an {@link MbmsException}
-     * being thrown with error code {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND}
-     * or {@link MbmsException.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY}
-     */
-    @Override
-    public void middlewareReady() {
-        // default implementation empty
-    }
-}
diff --git a/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java b/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java
index 339ff39..93a7cad 100644
--- a/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java
+++ b/telephony/java/android/telephony/mbms/MbmsDownloadReceiver.java
@@ -16,6 +16,7 @@
 
 package android.telephony.mbms;
 
+import android.annotation.SystemApi;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -24,7 +25,8 @@
 import android.content.pm.PackageManager;
 import android.net.Uri;
 import android.os.Bundle;
-import android.telephony.MbmsDownloadManager;
+import android.telephony.MbmsDownloadSession;
+import android.telephony.mbms.vendor.VendorUtils;
 import android.util.Log;
 
 import java.io.File;
@@ -34,52 +36,75 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
 import java.util.UUID;
 
 /**
+ * The {@link BroadcastReceiver} responsible for handling intents sent from the middleware. Apps
+ * that wish to download using MBMS APIs should declare this class in their AndroidManifest.xml as
+ * follows:
+<pre>{@code
+<receiver
+    android:name="android.telephony.mbms.MbmsDownloadReceiver"
+    android:permission="android.permission.SEND_EMBMS_INTENTS"
+    android:enabled="true"
+    android:exported="true">
+</receiver>}</pre>
  * @hide
  */
 public class MbmsDownloadReceiver extends BroadcastReceiver {
+    /** @hide */
     public static final String DOWNLOAD_TOKEN_SUFFIX = ".download_token";
+    /** @hide */
     public static final String MBMS_FILE_PROVIDER_META_DATA_KEY = "mbms-file-provider-authority";
 
     /**
-     * TODO: @SystemApi all these result codes
      * Indicates that the requested operation completed without error.
+     * @hide
      */
+    //@SystemApi
     public static final int RESULT_OK = 0;
 
     /**
      * Indicates that the intent sent had an invalid action. This will be the result if
      * {@link Intent#getAction()} returns anything other than
-     * {@link MbmsDownloadManager#ACTION_DOWNLOAD_RESULT_INTERNAL},
-     * {@link MbmsDownloadManager#ACTION_FILE_DESCRIPTOR_REQUEST}, or
-     * {@link MbmsDownloadManager#ACTION_CLEANUP}.
+     * {@link VendorUtils#ACTION_DOWNLOAD_RESULT_INTERNAL},
+     * {@link VendorUtils#ACTION_FILE_DESCRIPTOR_REQUEST}, or
+     * {@link VendorUtils#ACTION_CLEANUP}.
      * This is a fatal result code and no result extras should be expected.
+     * @hide
      */
+    //@SystemApi
     public static final int RESULT_INVALID_ACTION = 1;
 
     /**
      * Indicates that the intent was missing some required extras.
      * This is a fatal result code and no result extras should be expected.
+     * @hide
      */
+    //@SystemApi
     public static final int RESULT_MALFORMED_INTENT = 2;
 
     /**
-     * Indicates that the supplied value for {@link MbmsDownloadManager#EXTRA_TEMP_FILE_ROOT}
+     * Indicates that the supplied value for {@link VendorUtils#EXTRA_TEMP_FILE_ROOT}
      * does not match what the app has stored.
      * This is a fatal result code and no result extras should be expected.
+     * @hide
      */
+    //@SystemApi
     public static final int RESULT_BAD_TEMP_FILE_ROOT = 3;
 
     /**
      * Indicates that the manager was unable to move the completed download to its final location.
      * This is a fatal result code and no result extras should be expected.
+     * @hide
      */
+    //@SystemApi
     public static final int RESULT_DOWNLOAD_FINALIZATION_ERROR = 4;
 
     /**
@@ -87,35 +112,48 @@
      * descriptors.
      * This is a non-fatal result code -- some file descriptors may still be generated, but there
      * is no guarantee that they will be the same number as requested.
+     * @hide
      */
+    //@SystemApi
     public static final int RESULT_TEMP_FILE_GENERATION_ERROR = 5;
 
+    /**
+     * Indicates that the manager was unable to notify the app of the completed download.
+     * This is a fatal result code and no result extras should be expected.
+     * @hide
+     */
+    @SystemApi
+    public static final int RESULT_APP_NOTIFICATION_ERROR = 6;
+
+
     private static final String LOG_TAG = "MbmsDownloadReceiver";
     private static final String TEMP_FILE_SUFFIX = ".embms.temp";
-    private static final int MAX_TEMP_FILE_RETRIES = 5;
+    private static final String TEMP_FILE_STAGING_LOCATION = "staged_completed_files";
 
+    private static final int MAX_TEMP_FILE_RETRIES = 5;
 
     private String mFileProviderAuthorityCache = null;
     private String mMiddlewarePackageNameCache = null;
 
+    /** @hide */
     @Override
     public void onReceive(Context context, Intent intent) {
         if (!verifyIntentContents(context, intent)) {
             setResultCode(RESULT_MALFORMED_INTENT);
             return;
         }
-        if (!Objects.equals(intent.getStringExtra(MbmsDownloadManager.EXTRA_TEMP_FILE_ROOT),
+        if (!Objects.equals(intent.getStringExtra(VendorUtils.EXTRA_TEMP_FILE_ROOT),
                 MbmsTempFileProvider.getEmbmsTempFileDir(context).getPath())) {
             setResultCode(RESULT_BAD_TEMP_FILE_ROOT);
             return;
         }
 
-        if (MbmsDownloadManager.ACTION_DOWNLOAD_RESULT_INTERNAL.equals(intent.getAction())) {
+        if (VendorUtils.ACTION_DOWNLOAD_RESULT_INTERNAL.equals(intent.getAction())) {
             moveDownloadedFile(context, intent);
             cleanupPostMove(context, intent);
-        } else if (MbmsDownloadManager.ACTION_FILE_DESCRIPTOR_REQUEST.equals(intent.getAction())) {
+        } else if (VendorUtils.ACTION_FILE_DESCRIPTOR_REQUEST.equals(intent.getAction())) {
             generateTempFiles(context, intent);
-        } else if (MbmsDownloadManager.ACTION_CLEANUP.equals(intent.getAction())) {
+        } else if (VendorUtils.ACTION_CLEANUP.equals(intent.getAction())) {
             cleanupTempFiles(context, intent);
         } else {
             setResultCode(RESULT_INVALID_ACTION);
@@ -123,30 +161,31 @@
     }
 
     private boolean verifyIntentContents(Context context, Intent intent) {
-        if (MbmsDownloadManager.ACTION_DOWNLOAD_RESULT_INTERNAL.equals(intent.getAction())) {
-            if (!intent.hasExtra(MbmsDownloadManager.EXTRA_RESULT)) {
+        if (VendorUtils.ACTION_DOWNLOAD_RESULT_INTERNAL.equals(intent.getAction())) {
+            if (!intent.hasExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_RESULT)) {
                 Log.w(LOG_TAG, "Download result did not include a result code. Ignoring.");
                 return false;
             }
-            if (!intent.hasExtra(MbmsDownloadManager.EXTRA_REQUEST)) {
+            if (!intent.hasExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST)) {
                 Log.w(LOG_TAG, "Download result did not include the associated request. Ignoring.");
                 return false;
             }
-            if (!intent.hasExtra(MbmsDownloadManager.EXTRA_TEMP_FILE_ROOT)) {
+            if (!intent.hasExtra(VendorUtils.EXTRA_TEMP_FILE_ROOT)) {
                 Log.w(LOG_TAG, "Download result did not include the temp file root. Ignoring.");
                 return false;
             }
-            if (!intent.hasExtra(MbmsDownloadManager.EXTRA_FILE_INFO)) {
+            if (!intent.hasExtra(MbmsDownloadSession.EXTRA_MBMS_FILE_INFO)) {
                 Log.w(LOG_TAG, "Download result did not include the associated file info. " +
                         "Ignoring.");
                 return false;
             }
-            if (!intent.hasExtra(MbmsDownloadManager.EXTRA_FINAL_URI)) {
+            if (!intent.hasExtra(VendorUtils.EXTRA_FINAL_URI)) {
                 Log.w(LOG_TAG, "Download result did not include the path to the final " +
                         "temp file. Ignoring.");
                 return false;
             }
-            DownloadRequest request = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_REQUEST);
+            DownloadRequest request = intent.getParcelableExtra(
+                    MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST);
             String expectedTokenFileName = request.getHash() + DOWNLOAD_TOKEN_SUFFIX;
             File expectedTokenFile = new File(
                     MbmsUtils.getEmbmsTempFileDirForService(context, request.getFileServiceId()),
@@ -156,27 +195,27 @@
                         "Expected " + expectedTokenFile);
                 return false;
             }
-        } else if (MbmsDownloadManager.ACTION_FILE_DESCRIPTOR_REQUEST.equals(intent.getAction())) {
-            if (!intent.hasExtra(MbmsDownloadManager.EXTRA_SERVICE_INFO)) {
-                Log.w(LOG_TAG, "Temp file request did not include the associated service info." +
+        } else if (VendorUtils.ACTION_FILE_DESCRIPTOR_REQUEST.equals(intent.getAction())) {
+            if (!intent.hasExtra(VendorUtils.EXTRA_SERVICE_ID)) {
+                Log.w(LOG_TAG, "Temp file request did not include the associated service id." +
                         " Ignoring.");
                 return false;
             }
-            if (!intent.hasExtra(MbmsDownloadManager.EXTRA_TEMP_FILE_ROOT)) {
+            if (!intent.hasExtra(VendorUtils.EXTRA_TEMP_FILE_ROOT)) {
                 Log.w(LOG_TAG, "Download result did not include the temp file root. Ignoring.");
                 return false;
             }
-        } else if (MbmsDownloadManager.ACTION_CLEANUP.equals(intent.getAction())) {
-            if (!intent.hasExtra(MbmsDownloadManager.EXTRA_SERVICE_INFO)) {
-                Log.w(LOG_TAG, "Cleanup request did not include the associated service info." +
+        } else if (VendorUtils.ACTION_CLEANUP.equals(intent.getAction())) {
+            if (!intent.hasExtra(VendorUtils.EXTRA_SERVICE_ID)) {
+                Log.w(LOG_TAG, "Cleanup request did not include the associated service id." +
                         " Ignoring.");
                 return false;
             }
-            if (!intent.hasExtra(MbmsDownloadManager.EXTRA_TEMP_FILE_ROOT)) {
+            if (!intent.hasExtra(VendorUtils.EXTRA_TEMP_FILE_ROOT)) {
                 Log.w(LOG_TAG, "Cleanup request did not include the temp file root. Ignoring.");
                 return false;
             }
-            if (!intent.hasExtra(MbmsDownloadManager.EXTRA_TEMP_FILES_IN_USE)) {
+            if (!intent.hasExtra(VendorUtils.EXTRA_TEMP_FILES_IN_USE)) {
                 Log.w(LOG_TAG, "Cleanup request did not include the list of temp files in use. " +
                         "Ignoring.");
                 return false;
@@ -186,21 +225,26 @@
     }
 
     private void moveDownloadedFile(Context context, Intent intent) {
-        DownloadRequest request = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_REQUEST);
+        DownloadRequest request = intent.getParcelableExtra(
+                MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST);
         Intent intentForApp = request.getIntentForApp();
+        if (intentForApp == null) {
+            Log.i(LOG_TAG, "Malformed app notification intent");
+            setResultCode(RESULT_APP_NOTIFICATION_ERROR);
+            return;
+        }
 
-        int result = intent.getIntExtra(MbmsDownloadManager.EXTRA_RESULT,
-                MbmsDownloadManager.RESULT_CANCELLED);
-        intentForApp.putExtra(MbmsDownloadManager.EXTRA_RESULT, result);
+        int result = intent.getIntExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_RESULT,
+                MbmsDownloadSession.RESULT_CANCELLED);
+        intentForApp.putExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_RESULT, result);
 
-        if (result != MbmsDownloadManager.RESULT_SUCCESSFUL) {
+        if (result != MbmsDownloadSession.RESULT_SUCCESSFUL) {
             Log.i(LOG_TAG, "Download request indicated a failed download. Aborting.");
             context.sendBroadcast(intentForApp);
             return;
         }
 
-        Uri destinationUri = request.getDestinationUri();
-        Uri finalTempFile = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_FINAL_URI);
+        Uri finalTempFile = intent.getParcelableExtra(VendorUtils.EXTRA_FINAL_URI);
         if (!verifyTempFilePath(context, request.getFileServiceId(), finalTempFile)) {
             Log.w(LOG_TAG, "Download result specified an invalid temp file " + finalTempFile);
             setResultCode(RESULT_DOWNLOAD_FINALIZATION_ERROR);
@@ -208,30 +252,37 @@
         }
 
         FileInfo completedFileInfo =
-                (FileInfo) intent.getParcelableExtra(MbmsDownloadManager.EXTRA_FILE_INFO);
-        String relativePath = calculateDestinationFileRelativePath(request, completedFileInfo);
+                (FileInfo) intent.getParcelableExtra(MbmsDownloadSession.EXTRA_MBMS_FILE_INFO);
+        Path stagingDirectory = FileSystems.getDefault().getPath(
+                MbmsTempFileProvider.getEmbmsTempFileDir(context).getPath(),
+                TEMP_FILE_STAGING_LOCATION);
 
-        Uri finalFileLocation = moveTempFile(finalTempFile, destinationUri, relativePath);
-        if (finalFileLocation == null) {
+        Uri stagedFileLocation;
+        try {
+            stagedFileLocation = stageTempFile(finalTempFile, stagingDirectory);
+        } catch (IOException e) {
             Log.w(LOG_TAG, "Failed to move temp file to final destination");
             setResultCode(RESULT_DOWNLOAD_FINALIZATION_ERROR);
             return;
         }
-        intentForApp.putExtra(MbmsDownloadManager.EXTRA_COMPLETED_FILE_URI, finalFileLocation);
-        intentForApp.putExtra(MbmsDownloadManager.EXTRA_FILE_INFO, completedFileInfo);
+        intentForApp.putExtra(MbmsDownloadSession.EXTRA_MBMS_COMPLETED_FILE_URI,
+                stagedFileLocation);
+        intentForApp.putExtra(MbmsDownloadSession.EXTRA_MBMS_FILE_INFO, completedFileInfo);
+        intentForApp.putExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST, request);
 
         context.sendBroadcast(intentForApp);
         setResultCode(RESULT_OK);
     }
 
     private void cleanupPostMove(Context context, Intent intent) {
-        DownloadRequest request = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_REQUEST);
+        DownloadRequest request = intent.getParcelableExtra(
+                MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST);
         if (request == null) {
             Log.w(LOG_TAG, "Intent does not include a DownloadRequest. Ignoring.");
             return;
         }
 
-        List<Uri> tempFiles = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_TEMP_LIST);
+        List<Uri> tempFiles = intent.getParcelableExtra(VendorUtils.EXTRA_TEMP_LIST);
         if (tempFiles == null) {
             return;
         }
@@ -245,16 +296,15 @@
     }
 
     private void generateTempFiles(Context context, Intent intent) {
-        FileServiceInfo serviceInfo =
-                intent.getParcelableExtra(MbmsDownloadManager.EXTRA_SERVICE_INFO);
-        if (serviceInfo == null) {
-            Log.w(LOG_TAG, "Temp file request did not include the associated service info. " +
+        String serviceId = intent.getStringExtra(VendorUtils.EXTRA_SERVICE_ID);
+        if (serviceId == null) {
+            Log.w(LOG_TAG, "Temp file request did not include the associated service id. " +
                     "Ignoring.");
             setResultCode(RESULT_MALFORMED_INTENT);
             return;
         }
-        int fdCount = intent.getIntExtra(MbmsDownloadManager.EXTRA_FD_COUNT, 0);
-        List<Uri> pausedList = intent.getParcelableExtra(MbmsDownloadManager.EXTRA_PAUSED_LIST);
+        int fdCount = intent.getIntExtra(VendorUtils.EXTRA_FD_COUNT, 0);
+        List<Uri> pausedList = intent.getParcelableExtra(VendorUtils.EXTRA_PAUSED_LIST);
 
         if (fdCount == 0 && (pausedList == null || pausedList.size() == 0)) {
             Log.i(LOG_TAG, "No temp files actually requested. Ending.");
@@ -264,22 +314,20 @@
         }
 
         ArrayList<UriPathPair> freshTempFiles =
-                generateFreshTempFiles(context, serviceInfo, fdCount);
+                generateFreshTempFiles(context, serviceId, fdCount);
         ArrayList<UriPathPair> pausedFiles =
-                generateUrisForPausedFiles(context, serviceInfo, pausedList);
+                generateUrisForPausedFiles(context, serviceId, pausedList);
 
         Bundle result = new Bundle();
-        result.putParcelableArrayList(MbmsDownloadManager.EXTRA_FREE_URI_LIST, freshTempFiles);
-        result.putParcelableArrayList(MbmsDownloadManager.EXTRA_PAUSED_URI_LIST, pausedFiles);
+        result.putParcelableArrayList(VendorUtils.EXTRA_FREE_URI_LIST, freshTempFiles);
+        result.putParcelableArrayList(VendorUtils.EXTRA_PAUSED_URI_LIST, pausedFiles);
         setResultCode(RESULT_OK);
         setResultExtras(result);
     }
 
-    private ArrayList<UriPathPair> generateFreshTempFiles(Context context,
-            FileServiceInfo serviceInfo,
+    private ArrayList<UriPathPair> generateFreshTempFiles(Context context, String serviceId,
             int freshFdCount) {
-        File tempFileDir = MbmsUtils.getEmbmsTempFileDirForService(context,
-                serviceInfo.getServiceId());
+        File tempFileDir = MbmsUtils.getEmbmsTempFileDirForService(context, serviceId);
         if (!tempFileDir.exists()) {
             tempFileDir.mkdirs();
         }
@@ -323,14 +371,14 @@
     }
 
     private ArrayList<UriPathPair> generateUrisForPausedFiles(Context context,
-            FileServiceInfo serviceInfo, List<Uri> pausedFiles) {
+            String serviceId, List<Uri> pausedFiles) {
         if (pausedFiles == null) {
             return new ArrayList<>(0);
         }
         ArrayList<UriPathPair> result = new ArrayList<>(pausedFiles.size());
 
         for (Uri fileUri : pausedFiles) {
-            if (!verifyTempFilePath(context, serviceInfo.getServiceId(), fileUri)) {
+            if (!verifyTempFilePath(context, serviceId, fileUri)) {
                 Log.w(LOG_TAG, "Supplied file " + fileUri + " is not a valid temp file to resume");
                 setResultCode(RESULT_TEMP_FILE_GENERATION_ERROR);
                 continue;
@@ -352,12 +400,10 @@
     }
 
     private void cleanupTempFiles(Context context, Intent intent) {
-        FileServiceInfo serviceInfo =
-                intent.getParcelableExtra(MbmsDownloadManager.EXTRA_SERVICE_INFO);
-        File tempFileDir = MbmsUtils.getEmbmsTempFileDirForService(context,
-                serviceInfo.getServiceId());
+        String serviceId = intent.getStringExtra(VendorUtils.EXTRA_SERVICE_ID);
+        File tempFileDir = MbmsUtils.getEmbmsTempFileDirForService(context, serviceId);
         final List<Uri> filesInUse =
-                intent.getParcelableArrayListExtra(MbmsDownloadManager.EXTRA_TEMP_FILES_IN_USE);
+                intent.getParcelableArrayListExtra(VendorUtils.EXTRA_TEMP_FILES_IN_USE);
         File[] filesToDelete = tempFileDir.listFiles(new FileFilter() {
             @Override
             public boolean accept(File file) {
@@ -384,63 +430,22 @@
         }
     }
 
-    private static String calculateDestinationFileRelativePath(DownloadRequest request,
-            FileInfo info) {
-        List<String> filePathComponents = info.getUri().getPathSegments();
-        List<String> requestPathComponents = request.getSourceUri().getPathSegments();
-        Iterator<String> filePathIter = filePathComponents.iterator();
-        Iterator<String> requestPathIter = requestPathComponents.iterator();
-
-        StringBuilder pathBuilder = new StringBuilder();
-        // Iterate through the segments of the carrier's URI to the file, along with the segments
-        // of the source URI specified in the download request. The relative path is calculated
-        // as the tail of the file's URI that does not match the path segments in the source URI.
-        while (filePathIter.hasNext()) {
-            String currFilePathComponent = filePathIter.next();
-            if (requestPathIter.hasNext()) {
-                String requestFilePathComponent = requestPathIter.next();
-                if (requestFilePathComponent.equals(currFilePathComponent)) {
-                    continue;
-                }
-            }
-            pathBuilder.append(currFilePathComponent);
-            pathBuilder.append('/');
-        }
-        // remove the trailing slash
-        if (pathBuilder.length() > 0) {
-            pathBuilder.deleteCharAt(pathBuilder.length() - 1);
-        }
-        return pathBuilder.toString();
-    }
-
     /*
-     * Moves a tempfile located at fromPath to a new location at toPath. If
-     * toPath is a directory, the destination file will be located at  relativePath
-     * underneath toPath.
+     * Moves a tempfile located at fromPath to a new location in the staging directory.
      */
-    private static Uri moveTempFile(Uri fromPath, Uri toPath, String relativePath) {
+    private static Uri stageTempFile(Uri fromPath, Path stagingDirectory) throws IOException {
         if (!ContentResolver.SCHEME_FILE.equals(fromPath.getScheme())) {
             Log.w(LOG_TAG, "Moving source uri " + fromPath+ " does not have a file scheme");
             return null;
         }
-        if (!ContentResolver.SCHEME_FILE.equals(toPath.getScheme())) {
-            Log.w(LOG_TAG, "Moving destination uri " + toPath + " does not have a file scheme");
-            return null;
-        }
 
-        File fromFile = new File(fromPath.getSchemeSpecificPart());
-        File toFile = new File(toPath.getSchemeSpecificPart());
-        if (toFile.isDirectory()) {
-            toFile = new File(toFile, relativePath);
+        Path fromFile = FileSystems.getDefault().getPath(fromPath.getPath());
+        if (!Files.isDirectory(stagingDirectory)) {
+            Files.createDirectory(stagingDirectory);
         }
-        toFile.getParentFile().mkdirs();
+        Path result = Files.move(fromFile, stagingDirectory.resolve(fromFile.getFileName()));
 
-        if (fromFile.renameTo(toFile)) {
-            return Uri.fromFile(toFile);
-        } else if (manualMove(fromFile, toFile)) {
-            return Uri.fromFile(toFile);
-        }
-        return null;
+        return Uri.fromFile(result.toFile());
     }
 
     private static boolean verifyTempFilePath(Context context, String serviceId,
@@ -492,7 +497,7 @@
     private String getMiddlewarePackageCached(Context context) {
         if (mMiddlewarePackageNameCache == null) {
             mMiddlewarePackageNameCache = MbmsUtils.getMiddlewareServiceInfo(context,
-                    MbmsDownloadManager.MBMS_DOWNLOAD_SERVICE_ACTION).packageName;
+                    MbmsDownloadSession.MBMS_DOWNLOAD_SERVICE_ACTION).packageName;
         }
         return mMiddlewarePackageNameCache;
     }
diff --git a/telephony/java/android/telephony/mbms/MbmsDownloadSessionCallback.java b/telephony/java/android/telephony/mbms/MbmsDownloadSessionCallback.java
new file mode 100644
index 0000000..42bc775
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/MbmsDownloadSessionCallback.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2016 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.telephony.mbms;
+
+import android.telephony.MbmsDownloadSession;
+
+import java.util.List;
+
+/**
+ * A callback class that apps should use to receive information on file downloads over
+ * cell-broadcast.
+ * @hide
+ */
+public class MbmsDownloadSessionCallback {
+
+    /**
+     * Indicates that the middleware has encountered an asynchronous error.
+     * @param errorCode Any error code listed in {@link MbmsErrors}
+     * @param message A message, intended for debugging purposes, describing the error in further
+     *                detail.
+     */
+    public void onError(int errorCode, String message) {
+        // default implementation empty
+    }
+
+    /**
+     * Called to indicate published File Services have changed.
+     *
+     * This will only be called after the application has requested a list of file services and
+     * specified a service class list of interest via
+     * {@link MbmsDownloadSession#requestUpdateFileServices(List)}. If there are subsequent calls to
+     * {@link MbmsDownloadSession#requestUpdateFileServices(List)},
+     * this method may not be called again if
+     * the list of service classes would remain the same.
+     *
+     * @param services The most recently updated list of available file services.
+     */
+    public void onFileServicesUpdated(List<FileServiceInfo> services) {
+        // default implementation empty
+    }
+
+    /**
+     * Called to indicate that the middleware has been initialized and is ready.
+     *
+     * Before this method is called, calling any method on an instance of
+     * {@link MbmsDownloadSession} will result in an {@link IllegalStateException}
+     * being thrown or {@link #onError(int, String)} being called with error code
+     * {@link MbmsErrors.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY}
+     */
+    public void onMiddlewareReady() {
+        // default implementation empty
+    }
+}
diff --git a/telephony/java/android/telephony/mbms/MbmsException.java b/telephony/java/android/telephony/mbms/MbmsErrors.java
similarity index 86%
rename from telephony/java/android/telephony/mbms/MbmsException.java
rename to telephony/java/android/telephony/mbms/MbmsErrors.java
index 8888119..0195869 100644
--- a/telephony/java/android/telephony/mbms/MbmsException.java
+++ b/telephony/java/android/telephony/mbms/MbmsErrors.java
@@ -16,8 +16,10 @@
 
 package android.telephony.mbms;
 
+import android.telephony.MbmsStreamingSession;
+
 /** @hide */
-public class MbmsException extends Exception {
+public class MbmsErrors {
     /** Indicates that the operation was successful. */
     public static final int SUCCESS = 0;
 
@@ -31,8 +33,8 @@
 
     /**
      * Indicates that the app attempted to perform an operation on an instance of
-     * {@link android.telephony.MbmsDownloadManager} or
-     * {@link android.telephony.MbmsStreamingManager} without being bound to the middleware.
+     * {@link android.telephony.MbmsDownloadSession} or
+     * {@link MbmsStreamingSession} without being bound to the middleware.
      */
     public static final int ERROR_MIDDLEWARE_NOT_BOUND = 2;
 
@@ -44,10 +46,10 @@
      * middleware. They are applicable to both streaming and file-download use-cases.
      */
     public static class InitializationErrors {
+        private InitializationErrors() {}
         /**
          * Indicates that the app tried to create more than one instance each of
-         * {@link android.telephony.MbmsStreamingManager} or
-         * {@link android.telephony.MbmsDownloadManager}.
+         * {@link MbmsStreamingSession} or {@link android.telephony.MbmsDownloadSession}.
          */
         public static final int ERROR_DUPLICATE_INITIALIZE = 101;
         /** Indicates that the app is not authorized to access media via MBMS.*/
@@ -61,10 +63,11 @@
      * streaming and file-download.
      */
     public static class GeneralErrors {
+        private GeneralErrors() {}
         /**
          * Indicates that the app attempted to perform an operation before receiving notification
-         * that the middleware is ready via {@link MbmsStreamingManagerCallback#middlewareReady()}
-         * or {@link MbmsDownloadManagerCallback#middlewareReady()}.
+         * that the middleware is ready via {@link MbmsStreamingSessionCallback#onMiddlewareReady()}
+         * or {@link MbmsDownloadSessionCallback#onMiddlewareReady()}.
          */
         public static final int ERROR_MIDDLEWARE_NOT_YET_READY = 201;
         /**
@@ -97,6 +100,7 @@
      * Indicates the errors that are applicable only to the streaming use-case
      */
     public static class StreamingErrors {
+        private StreamingErrors() {}
         /** Indicates that the middleware cannot start a stream due to too many ongoing streams */
         public static final int ERROR_CONCURRENT_SERVICE_LIMIT_REACHED = 301;
 
@@ -105,7 +109,8 @@
 
         /**
          * Indicates that the app called
-         * {@link android.telephony.MbmsStreamingManager#startStreaming(StreamingServiceInfo, StreamingServiceCallback)}
+         * {@link MbmsStreamingSession#startStreaming(
+         * StreamingServiceInfo, StreamingServiceCallback, android.os.Handler)}
          * more than once for the same {@link StreamingServiceInfo}.
          */
         public static final int ERROR_DUPLICATE_START_STREAM = 303;
@@ -115,6 +120,7 @@
      * Indicates the errors that are applicable only to the file-download use-case
      */
     public static class DownloadErrors {
+        private DownloadErrors() { }
         /**
          * Indicates that the app is not allowed to change the temp file root at this time due to
          * outstanding download requests.
@@ -125,17 +131,5 @@
         public static final int ERROR_UNKNOWN_DOWNLOAD_REQUEST = 402;
     }
 
-    private final int mErrorCode;
-
-    /** @hide
-     * TODO: future systemapi
-     */
-    public MbmsException(int errorCode) {
-        super();
-        mErrorCode = errorCode;
-    }
-
-    public int getErrorCode() {
-        return mErrorCode;
-    }
+    private MbmsErrors() {}
 }
diff --git a/telephony/java/android/telephony/mbms/MbmsStreamingManagerCallback.java b/telephony/java/android/telephony/mbms/MbmsStreamingManagerCallback.java
deleted file mode 100644
index 2e91be9..0000000
--- a/telephony/java/android/telephony/mbms/MbmsStreamingManagerCallback.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2016 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.telephony.mbms;
-
-import java.util.List;
-
-/**
- * A Parcelable class with Cell-Broadcast service information.
- * @hide
- */
-public class MbmsStreamingManagerCallback extends IMbmsStreamingManagerCallback.Stub {
-
-    public final static int ERROR_CARRIER_NOT_SUPPORTED      = 1;
-    public final static int ERROR_UNABLE_TO_INITIALIZE       = 2;
-    public final static int ERROR_UNABLE_TO_ALLOCATE_MEMORY  = 3;
-
-
-    public void error(int errorCode, String message) {
-        // default implementation empty
-    }
-
-    /**
-     * Called to indicate published Streaming Services have changed.
-     *
-     * This will only be called after the application has requested
-     * a list of streaming services and specified a service class list
-     * of interest AND the results of a subsequent getStreamServices
-     * call with the same service class list would return different
-     * results.
-     *
-     * @param services a List of StreamingServiceInfos
-     *
-     */
-    public void streamingServicesUpdated(List<StreamingServiceInfo> services) {
-        // default implementation empty
-    }
-
-    /**
-     * Called to indicate that the middleware has been initialized and is ready.
-     *
-     * Before this method is called, calling any method on an instance of
-     * {@link android.telephony.MbmsStreamingManager} will result in an {@link MbmsException}
-     * being thrown with error code {@link MbmsException#ERROR_MIDDLEWARE_NOT_BOUND}
-     * or {@link MbmsException.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY}
-     */
-    @Override
-    public void middlewareReady() {
-        // default implementation empty
-    }
-}
diff --git a/telephony/java/android/telephony/mbms/MbmsStreamingSessionCallback.java b/telephony/java/android/telephony/mbms/MbmsStreamingSessionCallback.java
new file mode 100644
index 0000000..d714927
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/MbmsStreamingSessionCallback.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 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.telephony.mbms;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.os.Handler;
+import android.telephony.MbmsStreamingSession;
+
+import java.util.List;
+
+/**
+ * A callback class that is used to receive information from the middleware on MBMS streaming
+ * services. An instance of this object should be passed into
+ * {@link MbmsStreamingSession#create(Context, MbmsStreamingSessionCallback, int, Handler)}.
+ * @hide
+ */
+public class MbmsStreamingSessionCallback {
+    /**
+     * Called by the middleware when it has detected an error condition. The possible error codes
+     * are listed in {@link MbmsErrors}.
+     * @param errorCode The error code.
+     * @param message A human-readable message generated by the middleware for debugging purposes.
+     */
+    public void onError(int errorCode, @Nullable String message) {
+        // default implementation empty
+    }
+
+    /**
+     * Called to indicate published Streaming Services have changed.
+     *
+     * This will only be called after the application has requested
+     * a list of streaming services and specified a service class list
+     * of interest AND the results of a subsequent getStreamServices
+     * call with the same service class list would return different
+     * results.
+     *
+     * @param services The list of available services.
+     */
+    public void onStreamingServicesUpdated(List<StreamingServiceInfo> services) {
+        // default implementation empty
+    }
+
+    /**
+     * Called to indicate that the middleware has been initialized and is ready.
+     *
+     * Before this method is called, calling any method on an instance of
+     * {@link MbmsStreamingSession} will result in an {@link IllegalStateException} or an error
+     * delivered via {@link #onError(int, String)} with error code
+     * {@link MbmsErrors.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY}.
+     */
+    public void onMiddlewareReady() {
+        // default implementation empty
+    }
+}
diff --git a/telephony/java/android/telephony/mbms/MbmsTempFileProvider.java b/telephony/java/android/telephony/mbms/MbmsTempFileProvider.java
index c4d033b..689becd 100644
--- a/telephony/java/android/telephony/mbms/MbmsTempFileProvider.java
+++ b/telephony/java/android/telephony/mbms/MbmsTempFileProvider.java
@@ -23,12 +23,11 @@
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
 import android.content.pm.ProviderInfo;
 import android.database.Cursor;
 import android.net.Uri;
-import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
+import android.telephony.MbmsDownloadSession;
 
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -39,7 +38,6 @@
  * @hide
  */
 public class MbmsTempFileProvider extends ContentProvider {
-    public static final String DEFAULT_TOP_LEVEL_TEMP_DIRECTORY = "androidMbmsTempFileRoot";
     public static final String TEMP_FILE_ROOT_PREF_FILE_NAME = "MbmsTempFileRootPrefs";
     public static final String TEMP_FILE_ROOT_PREF_NAME = "mbms_temp_file_root";
 
@@ -182,8 +180,8 @@
             if (storedTempFileRoot != null) {
                 return new File(storedTempFileRoot).getCanonicalFile();
             } else {
-                return new File(context.getFilesDir(), DEFAULT_TOP_LEVEL_TEMP_DIRECTORY)
-                        .getCanonicalFile();
+                return new File(context.getFilesDir(),
+                        MbmsDownloadSession.DEFAULT_TOP_LEVEL_TEMP_DIRECTORY).getCanonicalFile();
             }
         } catch (IOException e) {
             throw new RuntimeException("Unable to canonicalize temp file root path " + e);
diff --git a/telephony/java/android/telephony/mbms/MbmsUtils.java b/telephony/java/android/telephony/mbms/MbmsUtils.java
index 4b913f8..d38d8a7 100644
--- a/telephony/java/android/telephony/mbms/MbmsUtils.java
+++ b/telephony/java/android/telephony/mbms/MbmsUtils.java
@@ -68,19 +68,20 @@
         return downloadServices.get(0).serviceInfo;
     }
 
-    public static void startBinding(Context context, String serviceAction,
-            ServiceConnection serviceConnection) throws MbmsException {
+    public static int startBinding(Context context, String serviceAction,
+            ServiceConnection serviceConnection) {
         Intent bindIntent = new Intent();
         ServiceInfo mbmsServiceInfo =
                 MbmsUtils.getMiddlewareServiceInfo(context, serviceAction);
 
         if (mbmsServiceInfo == null) {
-            throw new MbmsException(MbmsException.ERROR_NO_UNIQUE_MIDDLEWARE);
+            return MbmsErrors.ERROR_NO_UNIQUE_MIDDLEWARE;
         }
 
         bindIntent.setComponent(MbmsUtils.toComponentName(mbmsServiceInfo));
 
         context.bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE);
+        return MbmsErrors.SUCCESS;
     }
 
     /**
diff --git a/telephony/java/android/telephony/mbms/ServiceInfo.java b/telephony/java/android/telephony/mbms/ServiceInfo.java
index f9ad44c..3b9cc0e 100644
--- a/telephony/java/android/telephony/mbms/ServiceInfo.java
+++ b/telephony/java/android/telephony/mbms/ServiceInfo.java
@@ -16,6 +16,8 @@
 
 package android.telephony.mbms;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -26,47 +28,27 @@
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.NoSuchElementException;
 import java.util.Objects;
 import java.util.Set;
 
 /**
- * A Parcelable class with Cell-Broadcast service information.
+ * Describes a cell-broadcast service. This class should not be instantiated directly -- use
+ * {@link StreamingServiceInfo} or {@link FileServiceInfo}
  * @hide
  */
-public class ServiceInfo implements Parcelable {
+public class ServiceInfo {
     // arbitrary limit on the number of locale -> name pairs we support
     final static int MAP_LIMIT = 1000;
-    /**
-     * User displayable names listed by language.  Unmodifiable.
-     */
-    final Map<Locale, String> names;
 
-    /**
-     * The class name for this service - used to catagorize and filter
-     */
-    final String className;
+    private final Map<Locale, String> names;
+    private final String className;
+    private final List<Locale> locales;
+    private final String serviceId;
+    private final Date sessionStartTime;
+    private final Date sessionEndTime;
 
-    /**
-     * The languages available for this service content
-     */
-    final List<Locale> locales;
-
-    /**
-     * The carrier's identifier for the service.
-     */
-    final String serviceId;
-
-    /**
-     * The start time indicating when this service will be available.
-     */
-    final Date sessionStartTime;
-
-    /**
-     * The end time indicating when this sesion stops being available.
-     */
-    final Date sessionEndTime;
-
-
+    /** @hide */
     public ServiceInfo(Map<Locale, String> newNames, String newClassName, List<Locale> newLocales,
             String newServiceId, Date start, Date end) {
         if (newNames == null || newNames.isEmpty() || TextUtils.isEmpty(newClassName)
@@ -80,6 +62,13 @@
         if (newLocales.size() > MAP_LIMIT) {
             throw new RuntimeException("bad locales length " + newLocales.size());
         }
+
+        for (Locale l : newLocales) {
+            if (!newNames.containsKey(l)) {
+                throw new IllegalArgumentException("A name must be provided for each locale");
+            }
+        }
+
         names = new HashMap(newNames.size());
         names.putAll(newNames);
         className = newClassName;
@@ -89,20 +78,8 @@
         sessionEndTime = (Date)end.clone();
     }
 
-    public static final Parcelable.Creator<FileServiceInfo> CREATOR =
-            new Parcelable.Creator<FileServiceInfo>() {
-        @Override
-        public FileServiceInfo createFromParcel(Parcel source) {
-            return new FileServiceInfo(source);
-        }
-
-        @Override
-        public FileServiceInfo[] newArray(int size) {
-            return new FileServiceInfo[size];
-        }
-    };
-
-    ServiceInfo(Parcel in) {
+    /** @hide */
+    protected ServiceInfo(Parcel in) {
         int mapCount = in.readInt();
         if (mapCount > MAP_LIMIT || mapCount < 0) {
             throw new RuntimeException("bad map length" + mapCount);
@@ -128,7 +105,7 @@
         sessionEndTime = (java.util.Date) in.readSerializable();
     }
 
-    @Override
+    /** @hide */
     public void writeToParcel(Parcel dest, int flags) {
         Set<Locale> keySet = names.keySet();
         dest.writeInt(keySet.size());
@@ -147,31 +124,53 @@
         dest.writeSerializable(sessionEndTime);
     }
 
-    @Override
-    public int describeContents() {
-        return 0;
+    /**
+     * Get the user-displayable name for this cell-broadcast service corresponding to the
+     * provided {@link Locale}.
+     * @param locale The {@link Locale} in which you want the name of the service. This must be a
+     *               value from the list returned by {@link #getLocales()} -- an
+     *               {@link java.util.NoSuchElementException} may be thrown otherwise.
+     * @return The {@link CharSequence} providing the name of the service in the given
+     *         {@link Locale}
+     */
+    public @NonNull CharSequence getNameForLocale(@NonNull Locale locale) {
+        if (!names.containsKey(locale)) {
+            throw new NoSuchElementException("Locale not supported");
+        }
+        return names.get(locale);
     }
 
-    public Map<Locale, String> getNames() {
-        return names;
-    }
-
-    public String getClassName() {
+    /**
+     * The class name for this service - used to categorize and filter
+     */
+    public String getServiceClassName() {
         return className;
     }
 
+    /**
+     * The languages available for this service content
+     */
     public List<Locale> getLocales() {
         return locales;
     }
 
+    /**
+     * The carrier's identifier for the service.
+     */
     public String getServiceId() {
         return serviceId;
     }
 
+    /**
+     * The start time indicating when this service will be available.
+     */
     public Date getSessionStartTime() {
         return sessionStartTime;
     }
 
+    /**
+     * The end time indicating when this session stops being available.
+     */
     public Date getSessionEndTime() {
         return sessionEndTime;
     }
diff --git a/telephony/java/android/telephony/mbms/StreamingService.java b/telephony/java/android/telephony/mbms/StreamingService.java
index c49f8a9..ea9d70a 100644
--- a/telephony/java/android/telephony/mbms/StreamingService.java
+++ b/telephony/java/android/telephony/mbms/StreamingService.java
@@ -17,8 +17,10 @@
 package android.telephony.mbms;
 
 import android.annotation.IntDef;
+import android.annotation.Nullable;
 import android.net.Uri;
 import android.os.RemoteException;
+import android.telephony.MbmsStreamingSession;
 import android.telephony.mbms.vendor.IMbmsStreamingService;
 import android.util.Log;
 
@@ -26,13 +28,17 @@
 import java.lang.annotation.RetentionPolicy;
 
 /**
+ * Class used to represent a single MBMS stream. After a stream has been started with
+ * {@link MbmsStreamingSession#startStreaming(StreamingServiceInfo,
+ * StreamingServiceCallback, android.os.Handler)},
+ * this class is used to hold information about the stream and control it.
  * @hide
  */
 public class StreamingService {
     private static final String LOG_TAG = "MbmsStreamingService";
 
     /**
-     * The state of a stream, reported via {@link StreamingServiceCallback#streamStateUpdated}
+     * The state of a stream, reported via {@link StreamingServiceCallback#onStreamStateUpdated}
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
@@ -44,7 +50,7 @@
 
     /**
      * The reason for a stream state change, reported via
-     * {@link StreamingServiceCallback#streamStateUpdated}
+     * {@link StreamingServiceCallback#onStreamStateUpdated}
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
@@ -60,7 +66,8 @@
 
     /**
      * State changed due to a call to {@link #stopStreaming()} or
-     * {@link android.telephony.MbmsStreamingManager#startStreaming(StreamingServiceInfo, StreamingServiceCallback)}
+     * {@link MbmsStreamingSession#startStreaming(StreamingServiceInfo,
+     * StreamingServiceCallback, android.os.Handler)}
      */
     public static final int REASON_BY_USER_REQUEST = 1;
 
@@ -87,44 +94,46 @@
     /**
      * State changed due to the device leaving the where this stream is being broadcast.
      */
-    public static final int REASON_LEFT_MBMS_BROADCAST_AREA = 5;
+    public static final int REASON_LEFT_MBMS_BROADCAST_AREA = 6;
 
     /**
      * The method of transmission currently used for a stream,
-     * reported via {@link StreamingServiceCallback#streamMethodUpdated}
+     * reported via {@link StreamingServiceCallback#onStreamMethodUpdated}
      */
     public final static int BROADCAST_METHOD = 1;
     public final static int UNICAST_METHOD   = 2;
 
     private final int mSubscriptionId;
+    private final MbmsStreamingSession mParentSession;
     private final StreamingServiceInfo mServiceInfo;
-    private final IStreamingServiceCallback mCallback;
+    private final InternalStreamingServiceCallback mCallback;
 
     private IMbmsStreamingService mService;
+
     /**
      * @hide
      */
     public StreamingService(int subscriptionId,
             IMbmsStreamingService service,
+            MbmsStreamingSession session,
             StreamingServiceInfo streamingServiceInfo,
-            IStreamingServiceCallback callback) {
+            InternalStreamingServiceCallback callback) {
         mSubscriptionId = subscriptionId;
+        mParentSession = session;
         mService = service;
         mServiceInfo = streamingServiceInfo;
         mCallback = callback;
     }
 
     /**
-     * Retreive the Uri used to play this stream.
+     * Retrieve the Uri used to play this stream.
      *
-     * This may throw a {@link MbmsException} with the error code
-     * {@link MbmsException#ERROR_MIDDLEWARE_LOST}
+     * May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}.
      *
-     * May also throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
-     *
-     * @return The {@link Uri} to pass to the streaming client.
+     * @return The {@link Uri} to pass to the streaming client, or {@code null} if an error
+     *         occurred.
      */
-    public Uri getPlaybackUri() throws MbmsException {
+    public @Nullable Uri getPlaybackUri() {
         if (mService == null) {
             throw new IllegalStateException("No streaming service attached");
         }
@@ -134,25 +143,26 @@
         } catch (RemoteException e) {
             Log.w(LOG_TAG, "Remote process died");
             mService = null;
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
+            mParentSession.onStreamingServiceStopped(this);
+            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
+            return null;
         }
     }
 
     /**
-     * Retreive the info for this StreamingService.
+     * Retrieve the {@link StreamingServiceInfo} corresponding to this stream.
      */
     public StreamingServiceInfo getInfo() {
         return mServiceInfo;
     }
 
     /**
-     * Stop streaming this service.
-     * This may throw a {@link MbmsException} with the error code
-     * {@link MbmsException#ERROR_MIDDLEWARE_LOST}
+     * Stop streaming this service. Further operations on this object will fail with an
+     * {@link IllegalStateException}.
      *
-     * May also throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
+     * May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
      */
-    public void stopStreaming() throws MbmsException {
+    public void stopStreaming() {
         if (mService == null) {
             throw new IllegalStateException("No streaming service attached");
         }
@@ -162,32 +172,22 @@
         } catch (RemoteException e) {
             Log.w(LOG_TAG, "Remote process died");
             mService = null;
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
+            sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
+        } finally {
+            mParentSession.onStreamingServiceStopped(this);
         }
     }
 
-    /**
-     * Disposes of this stream. Further operations on this object will fail with an
-     * {@link IllegalStateException}.
-     *
-     * This may throw a {@link MbmsException} with the error code
-     * {@link MbmsException#ERROR_MIDDLEWARE_LOST}
-     * May also throw an {@link IllegalStateException}
-     */
-    public void dispose() throws MbmsException {
-        if (mService == null) {
-            throw new IllegalStateException("No streaming service attached");
-        }
+    /** @hide */
+    public InternalStreamingServiceCallback getCallback() {
+        return mCallback;
+    }
 
+    private void sendErrorToApp(int errorCode, String message) {
         try {
-            mService.disposeStream(mSubscriptionId, mServiceInfo.getServiceId());
+            mCallback.onError(errorCode, message);
         } catch (RemoteException e) {
-            Log.w(LOG_TAG, "Remote process died");
-            throw new MbmsException(MbmsException.ERROR_MIDDLEWARE_LOST);
-        } catch (IllegalArgumentException e) {
-            throw new IllegalStateException("StreamingService state inconsistent with middleware");
-        } finally {
-            mService = null;
+            // Ignore, should not happen locally.
         }
     }
 }
diff --git a/telephony/java/android/telephony/mbms/StreamingServiceCallback.java b/telephony/java/android/telephony/mbms/StreamingServiceCallback.java
index cab9c23..3c07961 100644
--- a/telephony/java/android/telephony/mbms/StreamingServiceCallback.java
+++ b/telephony/java/android/telephony/mbms/StreamingServiceCallback.java
@@ -16,11 +16,14 @@
 
 package android.telephony.mbms;
 
+import android.annotation.Nullable;
+
 /**
- * A Callback class for use when the application is actively streaming content.
+ * A callback class for use when the application is actively streaming content. The middleware
+ * will provide updates on the status of the stream via this callback.
  * @hide
  */
-public class StreamingServiceCallback extends IStreamingServiceCallback.Stub {
+public class StreamingServiceCallback {
 
     /**
      * Indicates broadcast signal strength is not available for this service.
@@ -31,8 +34,13 @@
      */
     public static final int SIGNAL_STRENGTH_UNAVAILABLE = -1;
 
-    @Override
-    public void error(int errorCode, String message) {
+    /**
+     * Called by the middleware when it has detected an error condition in this stream. The
+     * possible error codes are listed in {@link MbmsErrors}.
+     * @param errorCode The error code.
+     * @param message A human-readable message generated by the middleware for debugging purposes.
+     */
+    public void onError(int errorCode, @Nullable String message) {
         // default implementation empty
     }
 
@@ -42,8 +50,7 @@
      * See {@link StreamingService#STATE_STOPPED}, {@link StreamingService#STATE_STARTED}
      * and {@link StreamingService#STATE_STALLED}.
      */
-    @Override
-    public void streamStateUpdated(@StreamingService.StreamingState int state,
+    public void onStreamStateUpdated(@StreamingService.StreamingState int state,
             @StreamingService.StreamingStateChangeReason int reason) {
         // default implementation empty
     }
@@ -58,8 +65,7 @@
      * This may be called when a looping stream hits the end or
      * when parameters have changed to account for time drift.
      */
-    @Override
-    public void mediaDescriptionUpdated() {
+    public void onMediaDescriptionUpdated() {
         // default implementation empty
     }
 
@@ -73,8 +79,7 @@
      * {@link #SIGNAL_STRENGTH_UNAVAILABLE} if broadcast is not available
      * for this service due to timing, geography or popularity.
      */
-    @Override
-    public void broadcastSignalStrengthUpdated(int signalStrength) {
+    public void onBroadcastSignalStrengthUpdated(int signalStrength) {
         // default implementation empty
     }
 
@@ -94,8 +99,7 @@
      * See {@link StreamingService#BROADCAST_METHOD} and
      * {@link StreamingService#UNICAST_METHOD}
      */
-    @Override
-    public void streamMethodUpdated(int methodType) {
+    public void onStreamMethodUpdated(int methodType) {
         // default implementation empty
     }
 }
diff --git a/telephony/java/android/telephony/mbms/StreamingServiceInfo.java b/telephony/java/android/telephony/mbms/StreamingServiceInfo.java
index 77ce3bb..8e7917a 100644
--- a/telephony/java/android/telephony/mbms/StreamingServiceInfo.java
+++ b/telephony/java/android/telephony/mbms/StreamingServiceInfo.java
@@ -16,6 +16,7 @@
 
 package android.telephony.mbms;
 
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -25,15 +26,25 @@
 import java.util.Map;
 
 /**
- * A Parcelable class Cell-Broadcast media stream information.
- * This may not have any more info than ServiceInfo, but kept for completeness.
+ * Describes a single MBMS streaming service.
  * @hide
  */
-public class StreamingServiceInfo extends ServiceInfo implements Parcelable {
+public final class StreamingServiceInfo extends ServiceInfo implements Parcelable {
 
-    public StreamingServiceInfo(Map<Locale, String> newNames, String newClassName,
-            List<Locale> newLocales, String newServiceId, Date start, Date end) {
-        super(newNames, newClassName, newLocales, newServiceId, start, end);
+    /**
+     * @param names User displayable names listed by language.
+     * @param className The class name for this service - used by frontend apps to categorize and
+     *                  filter.
+     * @param locales The languages available for this service content.
+     * @param serviceId The carrier's identifier for the service.
+     * @param start The start time indicating when this service will be available.
+     * @param end The end time indicating when this session stops being available.
+     * @hide
+     */
+    @SystemApi
+    public StreamingServiceInfo(Map<Locale, String> names, String className,
+            List<Locale> locales, String serviceId, Date start, Date end) {
+        super(names, className, locales, serviceId, start, end);
     }
 
     public static final Parcelable.Creator<StreamingServiceInfo> CREATOR =
@@ -49,7 +60,7 @@
         }
     };
 
-    StreamingServiceInfo(Parcel in) {
+    private StreamingServiceInfo(Parcel in) {
         super(in);
     }
 
diff --git a/telephony/java/android/telephony/mbms/UriPathPair.java b/telephony/java/android/telephony/mbms/UriPathPair.java
index 7acc270..33bf785 100644
--- a/telephony/java/android/telephony/mbms/UriPathPair.java
+++ b/telephony/java/android/telephony/mbms/UriPathPair.java
@@ -16,13 +16,20 @@
 
 package android.telephony.mbms;
 
+import android.annotation.SystemApi;
 import android.content.ContentResolver;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.telephony.mbms.vendor.VendorUtils;
 
-/** @hide */
-public class UriPathPair implements Parcelable {
+/**
+ * Wrapper for a pair of {@link Uri}s that describe a temp file used by the middleware to
+ * download files via cell-broadcast.
+ * @hide
+ */
+//@SystemApi
+public final class UriPathPair implements Parcelable {
     private final Uri mFilePathUri;
     private final Uri mContentUri;
 
@@ -40,7 +47,7 @@
     }
 
     /** @hide */
-    protected UriPathPair(Parcel in) {
+    private UriPathPair(Parcel in) {
         mFilePathUri = in.readParcelable(Uri.class.getClassLoader());
         mContentUri = in.readParcelable(Uri.class.getClassLoader());
     }
@@ -57,12 +64,23 @@
         }
     };
 
-    /** future systemapi */
+    /**
+     * Returns the file-path {@link Uri}. This has scheme {@code file} and points to the actual
+     * location on disk where the temp file resides. Use this when sending {@link Uri}s back to the
+     * app in the intents in {@link VendorUtils}.
+     * @return A {@code file} {@link Uri}.
+     */
     public Uri getFilePathUri() {
         return mFilePathUri;
     }
 
-    /** future systemapi */
+    /**
+     * Returns the content {@link Uri} that may be used with
+     * {@link ContentResolver#openFileDescriptor(Uri, String)} to obtain a
+     * {@link android.os.ParcelFileDescriptor} to a temp file to write to. This {@link Uri} will
+     * expire if the middleware process dies.
+     * @return A {@code content} {@link Uri}
+     */
     public Uri getContentUri() {
         return mContentUri;
     }
diff --git a/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl b/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl
index dfcc5f7..ed5e826 100755
--- a/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl
+++ b/telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl
@@ -20,21 +20,26 @@
 import android.net.Uri;
 import android.telephony.mbms.DownloadRequest;
 import android.telephony.mbms.FileInfo;
-import android.telephony.mbms.IMbmsDownloadManagerCallback;
-import android.telephony.mbms.IDownloadProgressListener;
+import android.telephony.mbms.IMbmsDownloadSessionCallback;
+import android.telephony.mbms.IDownloadStateCallback;
 
 /**
  * @hide
  */
 interface IMbmsDownloadService
 {
-    int initialize(int subId, IMbmsDownloadManagerCallback listener);
+    int initialize(int subId, IMbmsDownloadSessionCallback listener);
 
-    int getFileServices(int subId, in List<String> serviceClasses);
+    int requestUpdateFileServices(int subId, in List<String> serviceClasses);
 
     int setTempFileRootDirectory(int subId, String rootDirectoryPath);
 
-    int download(in DownloadRequest downloadRequest, IDownloadProgressListener listener);
+    int download(in DownloadRequest downloadRequest);
+
+    int registerStateCallback(in DownloadRequest downloadRequest, IDownloadStateCallback listener);
+
+    int unregisterStateCallback(in DownloadRequest downloadRequest,
+        IDownloadStateCallback listener);
 
     List<DownloadRequest> listPendingDownloads(int subscriptionId);
 
diff --git a/telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl b/telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl
index 4dd4292..c90ffc7 100755
--- a/telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl
+++ b/telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl
@@ -17,7 +17,7 @@
 package android.telephony.mbms.vendor;
 
 import android.net.Uri;
-import android.telephony.mbms.IMbmsStreamingManagerCallback;
+import android.telephony.mbms.IMbmsStreamingSessionCallback;
 import android.telephony.mbms.IStreamingServiceCallback;
 import android.telephony.mbms.StreamingServiceInfo;
 
@@ -26,18 +26,16 @@
  */
 interface IMbmsStreamingService
 {
-    int initialize(IMbmsStreamingManagerCallback listener, int subId);
+    int initialize(IMbmsStreamingSessionCallback callback, int subId);
 
-    int getStreamingServices(int subId, in List<String> serviceClasses);
+    int requestUpdateStreamingServices(int subId, in List<String> serviceClasses);
 
     int startStreaming(int subId, String serviceId,
-            IStreamingServiceCallback listener);
+            IStreamingServiceCallback callback);
 
     Uri getPlaybackUri(int subId, String serviceId);
 
     void stopStreaming(int subId, String serviceId);
 
-    void disposeStream(int subId, String serviceId);
-
     void dispose(int subId);
 }
diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java
index edd5858..be686ee 100644
--- a/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java
+++ b/telephony/java/android/telephony/mbms/vendor/MbmsDownloadServiceBase.java
@@ -17,46 +17,103 @@
 package android.telephony.mbms.vendor;
 
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
 import android.os.RemoteException;
+import android.telephony.MbmsDownloadSession;
 import android.telephony.mbms.DownloadRequest;
+import android.telephony.mbms.DownloadStateCallback;
 import android.telephony.mbms.FileInfo;
-import android.telephony.mbms.IDownloadProgressListener;
-import android.telephony.mbms.IMbmsDownloadManagerCallback;
-import android.telephony.mbms.MbmsException;
+import android.telephony.mbms.FileServiceInfo;
+import android.telephony.mbms.IDownloadStateCallback;
+import android.telephony.mbms.IMbmsDownloadSessionCallback;
+import android.telephony.mbms.MbmsDownloadSessionCallback;
+import android.telephony.mbms.MbmsErrors;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
- * Base class for MbmsDownloadService. The middleware should extend this base class rather than
- * the aidl stub for compatibility
+ * Base class for MbmsDownloadService. The middleware should return an instance of this object from
+ * its {@link android.app.Service#onBind(Intent)} method.
  * @hide
- * TODO: future systemapi
  */
+//@SystemApi
 public class MbmsDownloadServiceBase extends IMbmsDownloadService.Stub {
+    private final Map<IBinder, DownloadStateCallback> mDownloadCallbackBinderMap = new HashMap<>();
+    private final Map<IBinder, DeathRecipient> mDownloadCallbackDeathRecipients = new HashMap<>();
+
     /**
      * Initialize the download service for this app and subId, registering the listener.
      *
      * May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}, which
      * will be intercepted and passed to the app as
-     * {@link android.telephony.mbms.MbmsException.InitializationErrors#ERROR_UNABLE_TO_INITIALIZE}
+     * {@link MbmsErrors.InitializationErrors#ERROR_UNABLE_TO_INITIALIZE}
      *
-     * May return any value from {@link android.telephony.mbms.MbmsException.InitializationErrors}
-     * or {@link MbmsException#SUCCESS}. Non-successful error codes will be passed to the app via
-     * {@link IMbmsDownloadManagerCallback#error(int, String)}.
+     * May return any value from {@link MbmsErrors.InitializationErrors}
+     * or {@link MbmsErrors#SUCCESS}. Non-successful error codes will be passed to the app via
+     * {@link IMbmsDownloadSessionCallback#onError(int, String)}.
      *
-     * @param listener The callback to use to communicate with the app.
+     * @param callback The callback to use to communicate with the app.
      * @param subscriptionId The subscription ID to use.
      */
-    @Override
-    public int initialize(int subscriptionId,
-            IMbmsDownloadManagerCallback listener) throws RemoteException {
+    public int initialize(int subscriptionId, MbmsDownloadSessionCallback callback)
+            throws RemoteException {
         return 0;
     }
 
     /**
+     * Actual AIDL implementation -- hides the callback AIDL from the API.
+     * @hide
+     */
+    @Override
+    public final int initialize(final int subscriptionId,
+            final IMbmsDownloadSessionCallback callback) throws RemoteException {
+        final int uid = Binder.getCallingUid();
+        callback.asBinder().linkToDeath(new DeathRecipient() {
+            @Override
+            public void binderDied() {
+                onAppCallbackDied(uid, subscriptionId);
+            }
+        }, 0);
+
+        return initialize(subscriptionId, new MbmsDownloadSessionCallback() {
+            @Override
+            public void onError(int errorCode, String message) {
+                try {
+                    callback.onError(errorCode, message);
+                } catch (RemoteException e) {
+                    onAppCallbackDied(uid, subscriptionId);
+                }
+            }
+
+            @Override
+            public void onFileServicesUpdated(List<FileServiceInfo> services) {
+                try {
+                    callback.onFileServicesUpdated(services);
+                } catch (RemoteException e) {
+                    onAppCallbackDied(uid, subscriptionId);
+                }
+            }
+
+            @Override
+            public void onMiddlewareReady() {
+                try {
+                    callback.onMiddlewareReady();
+                } catch (RemoteException e) {
+                    onAppCallbackDied(uid, subscriptionId);
+                }
+            }
+        });
+    }
+
+    /**
      * Registers serviceClasses of interest with the appName/subId key.
      * Starts async fetching data on streaming services of matching classes to be reported
-     * later via {@link IMbmsDownloadManagerCallback#fileServicesUpdated(List)}
+     * later via {@link IMbmsDownloadSessionCallback#onFileServicesUpdated(List)}
      *
      * Note that subsequent calls with the same uid and subId will replace
      * the service class list.
@@ -67,11 +124,11 @@
      * @param serviceClasses The service classes that the app wishes to get info on. The strings
      *                       may contain arbitrary data as negotiated between the app and the
      *                       carrier.
-     * @return One of {@link MbmsException#SUCCESS} or
-     *         {@link MbmsException.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY},
+     * @return One of {@link MbmsErrors#SUCCESS} or
+     *         {@link MbmsErrors.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY},
      */
     @Override
-    public int getFileServices(int subscriptionId, List<String> serviceClasses)
+    public int requestUpdateFileServices(int subscriptionId, List<String> serviceClasses)
             throws RemoteException {
         return 0;
     }
@@ -83,13 +140,13 @@
      *
      * If the calling app (as identified by the calling UID) currently has any pending download
      * requests that have not been canceled, the middleware must return
-     * {@link MbmsException.DownloadErrors#ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT} here.
+     * {@link MbmsErrors.DownloadErrors#ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT} here.
      *
      * @param subscriptionId The subscription id the download is operating under.
      * @param rootDirectoryPath The path to the app's temp file root directory.
-     * @return {@link MbmsException#SUCCESS},
-     *         {@link MbmsException.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY} or
-     *         {@link MbmsException.DownloadErrors#ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT}
+     * @return {@link MbmsErrors#SUCCESS},
+     *         {@link MbmsErrors.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY} or
+     *         {@link MbmsErrors.DownloadErrors#ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT}
      */
     @Override
     public int setTempFileRootDirectory(int subscriptionId,
@@ -105,21 +162,135 @@
      * this is not the case, an {@link IllegalStateException} may be thrown.
      *
      * @param downloadRequest An object describing the set of files to be downloaded.
-     * @param listener A listener through which the middleware can provide progress updates to
-     *                 the app while both are still running.
-     * @return TODO: enumerate possible return values
+     * @return Any error from {@link MbmsErrors.GeneralErrors}
+     *         or {@link MbmsErrors#SUCCESS}
      */
     @Override
-    public int download(DownloadRequest downloadRequest, IDownloadProgressListener listener)
-            throws RemoteException {
+    public int download(DownloadRequest downloadRequest) throws RemoteException {
         return 0;
     }
 
+    /**
+     * Registers a download state callbacks for the provided {@link DownloadRequest}.
+     *
+     * This method is called by the app when it wants to request updates on the progress or
+     * status of the download.
+     *
+     * If the middleware is not aware of a download having been requested with the provided
+     *
+     * {@link DownloadRequest} in the past,
+     * {@link MbmsErrors.DownloadErrors#ERROR_UNKNOWN_DOWNLOAD_REQUEST}
+     * must be returned.
+     *
+     * @param downloadRequest The {@link DownloadRequest} that was used to initiate the download
+     *                        for which progress updates are being requested.
+     * @param callback The callback object to use.
+     */
+    public int registerStateCallback(DownloadRequest downloadRequest,
+            DownloadStateCallback callback) throws RemoteException {
+        return 0;
+    }
+
+    /**
+     * Actual AIDL implementation -- hides the callback AIDL from the API.
+     * @hide
+     */
+    @Override
+    public final int registerStateCallback(
+            final DownloadRequest downloadRequest, final IDownloadStateCallback callback)
+            throws RemoteException {
+        final int uid = Binder.getCallingUid();
+        DeathRecipient deathRecipient = new DeathRecipient() {
+            @Override
+            public void binderDied() {
+                onAppCallbackDied(uid, downloadRequest.getSubscriptionId());
+                mDownloadCallbackBinderMap.remove(callback.asBinder());
+                mDownloadCallbackDeathRecipients.remove(callback.asBinder());
+            }
+        };
+        mDownloadCallbackDeathRecipients.put(callback.asBinder(), deathRecipient);
+        callback.asBinder().linkToDeath(deathRecipient, 0);
+
+        DownloadStateCallback exposedCallback = new DownloadStateCallback() {
+            @Override
+            public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo, int
+                    currentDownloadSize, int fullDownloadSize, int currentDecodedSize, int
+                    fullDecodedSize) {
+                try {
+                    callback.onProgressUpdated(request, fileInfo, currentDownloadSize,
+                            fullDownloadSize,
+                            currentDecodedSize, fullDecodedSize);
+                } catch (RemoteException e) {
+                    onAppCallbackDied(uid, downloadRequest.getSubscriptionId());
+                }
+            }
+
+            @Override
+            public void onStateUpdated(DownloadRequest request, FileInfo fileInfo,
+                    @MbmsDownloadSession.DownloadStatus int state) {
+                try {
+                    callback.onStateUpdated(request, fileInfo, state);
+                } catch (RemoteException e) {
+                    onAppCallbackDied(uid, downloadRequest.getSubscriptionId());
+                }
+            }
+        };
+
+        mDownloadCallbackBinderMap.put(callback.asBinder(), exposedCallback);
+
+        return registerStateCallback(downloadRequest, exposedCallback);
+    }
+
+    /**
+     * Un-registers a download state callbacks for the provided {@link DownloadRequest}.
+     *
+     * This method is called by the app when it no longer wants to request updates on the
+     * download.
+     *
+     * If the middleware is not aware of a download having been requested with the provided
+     * {@link DownloadRequest} in the past,
+     * {@link MbmsErrors.DownloadErrors#ERROR_UNKNOWN_DOWNLOAD_REQUEST}
+     * must be returned.
+     *
+     * @param downloadRequest The {@link DownloadRequest} that was used to register the callback
+     * @param callback The callback object that
+     *                 {@link #registerStateCallback(DownloadRequest, DownloadStateCallback)}
+     *                 was called with.
+     */
+    public int unregisterStateCallback(DownloadRequest downloadRequest,
+            DownloadStateCallback callback) throws RemoteException {
+        return 0;
+    }
+
+    /**
+     * Actual AIDL implementation -- hides the callback AIDL from the API.
+     * @hide
+     */
+    @Override
+    public final int unregisterStateCallback(
+            final DownloadRequest downloadRequest, final IDownloadStateCallback callback)
+            throws RemoteException {
+        DeathRecipient deathRecipient =
+                mDownloadCallbackDeathRecipients.remove(callback.asBinder());
+        if (deathRecipient == null) {
+            throw new IllegalArgumentException("Unknown callback");
+        }
+
+        callback.asBinder().unlinkToDeath(deathRecipient, 0);
+
+        DownloadStateCallback exposedCallback =
+                mDownloadCallbackBinderMap.remove(callback.asBinder());
+        if (exposedCallback == null) {
+            throw new IllegalArgumentException("Unknown callback");
+        }
+
+        return unregisterStateCallback(downloadRequest, exposedCallback);
+    }
 
     /**
      * Returns a list of pending {@link DownloadRequest}s that originated from the calling
      * application, identified by its uid. A pending request is one that was issued via
-     * {@link #download(DownloadRequest, IDownloadCallback)} but not cancelled through
+     * {@link #download(DownloadRequest)} but not cancelled through
      * {@link #cancelDownload(DownloadRequest)}.
      * The middleware must return a non-null result synchronously or throw an exception
      * inheriting from {@link RuntimeException}.
@@ -135,13 +306,13 @@
      * Issues a request to cancel the specified download request.
      *
      * If the middleware is unable to cancel the request for whatever reason, it should return
-     * synchronously with an error. If this method returns {@link MbmsException#SUCCESS}, the app
+     * synchronously with an error. If this method returns {@link MbmsErrors#SUCCESS}, the app
      * will no longer be expecting any more file-completed intents from the middleware for this
      * {@link DownloadRequest}.
      * @param downloadRequest The request to cancel
-     * @return {@link MbmsException#SUCCESS},
-     *         {@link MbmsException.DownloadErrors#ERROR_UNKNOWN_DOWNLOAD_REQUEST},
-     *         {@link MbmsException.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY}
+     * @return {@link MbmsErrors#SUCCESS},
+     *         {@link MbmsErrors.DownloadErrors#ERROR_UNKNOWN_DOWNLOAD_REQUEST},
+     *         {@link MbmsErrors.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY}
      */
     @Override
     public int cancelDownload(DownloadRequest downloadRequest) throws RemoteException {
@@ -153,7 +324,7 @@
      *
      * If the middleware has not yet been properly initialized or if it has no records of the
      * file indicated by {@code fileInfo} being associated with {@code downloadRequest},
-     * {@link android.telephony.MbmsDownloadManager#STATUS_UNKNOWN} must be returned.
+     * {@link MbmsDownloadSession#STATUS_UNKNOWN} must be returned.
      *
      * @param downloadRequest The download request to query.
      * @param fileInfo The particular file within the request to get information on.
@@ -173,7 +344,7 @@
      * In addition, current in-progress downloads must not be interrupted.
      *
      * If the middleware is not aware of the specified download request, return
-     * {@link MbmsException.DownloadErrors#ERROR_UNKNOWN_DOWNLOAD_REQUEST}.
+     * {@link MbmsErrors.DownloadErrors#ERROR_UNKNOWN_DOWNLOAD_REQUEST}.
      *
      * @param downloadRequest The request to re-download files for.
      */
@@ -187,7 +358,7 @@
      * Signals that the app wishes to dispose of the session identified by the
      * {@code subscriptionId} argument and the caller's uid. No notification back to the
      * app is required for this operation, and the corresponding callback provided via
-     * {@link #initialize(int, IMbmsDownloadManagerCallback)} should no longer be used
+     * {@link #initialize(int, IMbmsDownloadSessionCallback)} should no longer be used
      * after this method has been called by the app.
      *
      * Any download requests issued by the app should remain in effect until the app calls
@@ -200,4 +371,12 @@
     @Override
     public void dispose(int subscriptionId) throws RemoteException {
     }
+
+    /**
+     * Indicates that the app identified by the given UID and subscription ID has died.
+     * @param uid the UID of the app, as returned by {@link Binder#getCallingUid()}.
+     * @param subscriptionId The subscription ID the app is using.
+     */
+    public void onAppCallbackDied(int uid, int subscriptionId) {
+    }
 }
diff --git a/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java b/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
index 585d5b9..f998f2e 100644
--- a/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
+++ b/telephony/java/android/telephony/mbms/vendor/MbmsStreamingServiceBase.java
@@ -17,43 +17,97 @@
 package android.telephony.mbms.vendor;
 
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.Intent;
 import android.net.Uri;
+import android.os.Binder;
 import android.os.RemoteException;
-import android.telephony.mbms.IMbmsStreamingManagerCallback;
+import android.telephony.mbms.IMbmsStreamingSessionCallback;
 import android.telephony.mbms.IStreamingServiceCallback;
-import android.telephony.mbms.MbmsException;
+import android.telephony.mbms.MbmsErrors;
+import android.telephony.mbms.MbmsStreamingSessionCallback;
+import android.telephony.mbms.StreamingService;
+import android.telephony.mbms.StreamingServiceCallback;
+import android.telephony.mbms.StreamingServiceInfo;
 
 import java.util.List;
 
 /**
+ * Base class for MBMS streaming services. The middleware should return an instance of this
+ * object from its {@link android.app.Service#onBind(Intent)} method.
  * @hide
- * TODO: future systemapi
  */
+//@SystemApi
 public class MbmsStreamingServiceBase extends IMbmsStreamingService.Stub {
     /**
      * Initialize streaming service for this app and subId, registering the listener.
      *
-     * May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}, which
+     * May throw an {@link IllegalArgumentException} or a {@link SecurityException}, which
      * will be intercepted and passed to the app as
-     * {@link android.telephony.mbms.MbmsException.InitializationErrors#ERROR_UNABLE_TO_INITIALIZE}
+     * {@link MbmsErrors.InitializationErrors#ERROR_UNABLE_TO_INITIALIZE}
      *
-     * May return any value from {@link android.telephony.mbms.MbmsException.InitializationErrors}
-     * or {@link MbmsException#SUCCESS}. Non-successful error codes will be passed to the app via
-     * {@link IMbmsStreamingManagerCallback#error(int, String)}.
+     * May return any value from {@link MbmsErrors.InitializationErrors}
+     * or {@link MbmsErrors#SUCCESS}. Non-successful error codes will be passed to the app via
+     * {@link IMbmsStreamingSessionCallback#onError(int, String)}.
      *
-     * @param listener The callback to use to communicate with the app.
+     * @param callback The callback to use to communicate with the app.
      * @param subscriptionId The subscription ID to use.
      */
-    @Override
-    public int initialize(IMbmsStreamingManagerCallback listener, int subscriptionId)
+    public int initialize(MbmsStreamingSessionCallback callback, int subscriptionId)
             throws RemoteException {
         return 0;
     }
 
     /**
+     * Actual AIDL implementation that hides the callback AIDL from the middleware.
+     * @hide
+     */
+    @Override
+    public final int initialize(final IMbmsStreamingSessionCallback callback,
+            final int subscriptionId) throws RemoteException {
+        final int uid = Binder.getCallingUid();
+        callback.asBinder().linkToDeath(new DeathRecipient() {
+            @Override
+            public void binderDied() {
+                onAppCallbackDied(uid, subscriptionId);
+            }
+        }, 0);
+
+        return initialize(new MbmsStreamingSessionCallback() {
+            @Override
+            public void onError(final int errorCode, final String message) {
+                try {
+                    callback.onError(errorCode, message);
+                } catch (RemoteException e) {
+                    onAppCallbackDied(uid, subscriptionId);
+                }
+            }
+
+            @Override
+            public void onStreamingServicesUpdated(final List<StreamingServiceInfo> services) {
+                try {
+                    callback.onStreamingServicesUpdated(services);
+                } catch (RemoteException e) {
+                    onAppCallbackDied(uid, subscriptionId);
+                }
+            }
+
+            @Override
+            public void onMiddlewareReady() {
+                try {
+                    callback.onMiddlewareReady();
+                } catch (RemoteException e) {
+                    onAppCallbackDied(uid, subscriptionId);
+                }
+            }
+        }, subscriptionId);
+    }
+
+
+    /**
      * Registers serviceClasses of interest with the appName/subId key.
      * Starts async fetching data on streaming services of matching classes to be reported
-     * later via {@link IMbmsStreamingManagerCallback#streamingServicesUpdated(List)}
+     * later via {@link IMbmsStreamingSessionCallback#onStreamingServicesUpdated(List)}
      *
      * Note that subsequent calls with the same uid and subId will replace
      * the service class list.
@@ -64,11 +118,11 @@
      * @param serviceClasses The service classes that the app wishes to get info on. The strings
      *                       may contain arbitrary data as negotiated between the app and the
      *                       carrier.
-     * @return {@link MbmsException#SUCCESS} or any of the errors in
-     * {@link android.telephony.mbms.MbmsException.GeneralErrors}
+     * @return {@link MbmsErrors#SUCCESS} or any of the errors in
+     * {@link MbmsErrors.GeneralErrors}
      */
     @Override
-    public int getStreamingServices(int subscriptionId,
+    public int requestUpdateStreamingServices(int subscriptionId,
             List<String> serviceClasses) throws RemoteException {
         return 0;
     }
@@ -76,19 +130,83 @@
     /**
      * Starts streaming on a particular service. This method may perform asynchronous work. When
      * the middleware is ready to send bits to the frontend, it should inform the app via
-     * {@link IStreamingServiceCallback#streamStateUpdated(int, int)}.
+     * {@link IStreamingServiceCallback#onStreamStateUpdated(int, int)}.
      *
      * May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
      *
      * @param subscriptionId The subscription id to use.
      * @param serviceId The ID of the streaming service that the app has requested.
-     * @param listener The listener object on which the app wishes to receive updates.
-     * @return Any error in {@link android.telephony.mbms.MbmsException.GeneralErrors}
+     * @param callback The callback object on which the app wishes to receive updates.
+     * @return Any error in {@link MbmsErrors.GeneralErrors}
+     */
+    public int startStreaming(int subscriptionId, String serviceId,
+            StreamingServiceCallback callback) throws RemoteException {
+        return 0;
+    }
+
+    /**
+     * Actual AIDL implementation of startStreaming that hides the callback AIDL from the
+     * middleware.
+     * @hide
      */
     @Override
-    public int startStreaming(int subscriptionId, String serviceId,
-            IStreamingServiceCallback listener) throws RemoteException {
-        return 0;
+    public int startStreaming(final int subscriptionId, String serviceId,
+            final IStreamingServiceCallback callback) throws RemoteException {
+        final int uid = Binder.getCallingUid();
+        callback.asBinder().linkToDeath(new DeathRecipient() {
+            @Override
+            public void binderDied() {
+                onAppCallbackDied(uid, subscriptionId);
+            }
+        }, 0);
+
+        return startStreaming(subscriptionId, serviceId, new StreamingServiceCallback() {
+            @Override
+            public void onError(final int errorCode, final String message) {
+                try {
+                    callback.onError(errorCode, message);
+                } catch (RemoteException e) {
+                    onAppCallbackDied(uid, subscriptionId);
+                }
+            }
+
+            @Override
+            public void onStreamStateUpdated(@StreamingService.StreamingState final int state,
+                    @StreamingService.StreamingStateChangeReason final int reason) {
+                try {
+                    callback.onStreamStateUpdated(state, reason);
+                } catch (RemoteException e) {
+                    onAppCallbackDied(uid, subscriptionId);
+                }
+            }
+
+            @Override
+            public void onMediaDescriptionUpdated() {
+                try {
+                    callback.onMediaDescriptionUpdated();
+                } catch (RemoteException e) {
+                    onAppCallbackDied(uid, subscriptionId);
+                }
+            }
+
+            @Override
+            public void onBroadcastSignalStrengthUpdated(final int signalStrength) {
+                try {
+                    callback.onBroadcastSignalStrengthUpdated(signalStrength);
+                } catch (RemoteException e) {
+                    onAppCallbackDied(uid, subscriptionId);
+                }
+            }
+
+            @Override
+            public void onStreamMethodUpdated(final int methodType) {
+                try {
+                    callback.onStreamMethodUpdated(methodType);
+                } catch (RemoteException e) {
+                    onAppCallbackDied(uid, subscriptionId);
+                }
+            }
+        });
     }
 
     /**
@@ -110,7 +228,11 @@
     /**
      * Stop streaming the stream identified by {@code serviceId}. Notification of the resulting
      * stream state change should be reported to the app via
-     * {@link IStreamingServiceCallback#streamStateUpdated(int, int)}.
+     * {@link IStreamingServiceCallback#onStreamStateUpdated(int, int)}.
+     *
+     * In addition, the callback provided via
+     * {@link #startStreaming(int, String, IStreamingServiceCallback)} should no longer be
+     * used after this method has called by the app.
      *
      * May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
      *
@@ -123,27 +245,10 @@
     }
 
     /**
-     * Dispose of the stream identified by {@code serviceId} for the app identified by the
-     * {@code appName} and {@code subscriptionId} arguments along with the caller's uid.
-     * No notification back to the app is required for this operation, and the callback provided via
-     * {@link #startStreaming(int, String, IStreamingServiceCallback)} should no longer be
-     * used after this method has called by the app.
-     *
-     * May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
-     *
-     * @param subscriptionId The subscription id to use.
-     * @param serviceId The ID of the streaming service that the app wishes to dispose of.
-     */
-    @Override
-    public void disposeStream(int subscriptionId, String serviceId)
-            throws RemoteException {
-    }
-
-    /**
      * Signals that the app wishes to dispose of the session identified by the
      * {@code subscriptionId} argument and the caller's uid. No notification back to the
      * app is required for this operation, and the corresponding callback provided via
-     * {@link #initialize(IMbmsStreamingManagerCallback, int)} should no longer be used
+     * {@link #initialize(IMbmsStreamingSessionCallback, int)} should no longer be used
      * after this method has been called by the app.
      *
      * May throw an {@link IllegalStateException}
@@ -153,4 +258,12 @@
     @Override
     public void dispose(int subscriptionId) throws RemoteException {
     }
+
+    /**
+     * Indicates that the app identified by the given UID and subscription ID has died.
+     * @param uid the UID of the app, as returned by {@link Binder#getCallingUid()}.
+     * @param subscriptionId The subscription ID the app is using.
+     */
+    public void onAppCallbackDied(int uid, int subscriptionId) {
+    }
 }
diff --git a/telephony/java/android/telephony/mbms/vendor/VendorUtils.java b/telephony/java/android/telephony/mbms/vendor/VendorUtils.java
new file mode 100644
index 0000000..7bab734
--- /dev/null
+++ b/telephony/java/android/telephony/mbms/vendor/VendorUtils.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2017 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.telephony.mbms.vendor;
+
+import android.annotation.SystemApi;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.telephony.MbmsDownloadSession;
+import android.telephony.mbms.MbmsDownloadReceiver;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * Contains constants and utility methods for MBMS Download middleware apps to communicate with
+ * frontend apps.
+ * @hide
+ */
+//@SystemApi
+public class VendorUtils {
+
+    /**
+     * The MBMS middleware should send this when a download of single file has completed or
+     * failed. Mandatory extras are
+     * {@link MbmsDownloadSession#EXTRA_MBMS_DOWNLOAD_RESULT}
+     * {@link MbmsDownloadSession#EXTRA_MBMS_FILE_INFO}
+     * {@link MbmsDownloadSession#EXTRA_MBMS_DOWNLOAD_REQUEST}
+     * {@link #EXTRA_TEMP_LIST}
+     * {@link #EXTRA_FINAL_URI}
+     */
+    public static final String ACTION_DOWNLOAD_RESULT_INTERNAL =
+            "android.telephony.mbms.action.DOWNLOAD_RESULT_INTERNAL";
+
+    /**
+     * The MBMS middleware should send this when it wishes to request {@code content://} URIs to
+     * serve as temp files for downloads or when it wishes to resume paused downloads. Mandatory
+     * extras are
+     * {@link #EXTRA_SERVICE_ID}
+     *
+     * Optional extras are
+     * {@link #EXTRA_FD_COUNT} (0 if not present)
+     * {@link #EXTRA_PAUSED_LIST} (empty if not present)
+     */
+    public static final String ACTION_FILE_DESCRIPTOR_REQUEST =
+            "android.telephony.mbms.action.FILE_DESCRIPTOR_REQUEST";
+
+    /**
+     * The MBMS middleware should send this when it wishes to clean up temp  files in the app's
+     * filesystem. Mandatory extras are:
+     * {@link #EXTRA_TEMP_FILES_IN_USE}
+     */
+    public static final String ACTION_CLEANUP =
+            "android.telephony.mbms.action.CLEANUP";
+
+    /**
+     * Extra containing a {@link List} of {@link Uri}s that were used as temp files for this
+     * completed file. These {@link Uri}s should have scheme {@code file://}, and the temp
+     * files will be deleted upon receipt of the intent.
+     * May be null.
+     */
+    public static final String EXTRA_TEMP_LIST = "android.telephony.mbms.extra.TEMP_LIST";
+
+    /**
+     * Extra containing an integer indicating the number of temp files requested.
+     */
+    public static final String EXTRA_FD_COUNT = "android.telephony.mbms.extra.FD_COUNT";
+
+    /**
+     * Extra containing a list of {@link Uri}s that the middleware is requesting access to via
+     * {@link #ACTION_FILE_DESCRIPTOR_REQUEST} in order to resume downloading. These {@link Uri}s
+     * should have scheme {@code file://}.
+     */
+    public static final String EXTRA_PAUSED_LIST = "android.telephony.mbms.extra.PAUSED_LIST";
+
+    /**
+     * Extra containing a list of {@link android.telephony.mbms.UriPathPair}s, used in the
+     * response to {@link #ACTION_FILE_DESCRIPTOR_REQUEST}. These are temp files that are meant
+     * to be used for new file downloads.
+     */
+    public static final String EXTRA_FREE_URI_LIST = "android.telephony.mbms.extra.FREE_URI_LIST";
+
+    /**
+     * Extra containing a list of {@link android.telephony.mbms.UriPathPair}s, used in the
+     * response to {@link #ACTION_FILE_DESCRIPTOR_REQUEST}. These
+     * {@link android.telephony.mbms.UriPathPair}s contain {@code content://} URIs that provide
+     * access to previously paused downloads.
+     */
+    public static final String EXTRA_PAUSED_URI_LIST =
+            "android.telephony.mbms.extra.PAUSED_URI_LIST";
+
+    /**
+     * Extra containing a string that points to the middleware's knowledge of where the temp file
+     * root for the app is. The path should be a canonical path as returned by
+     * {@link File#getCanonicalPath()}
+     */
+    public static final String EXTRA_TEMP_FILE_ROOT =
+            "android.telephony.mbms.extra.TEMP_FILE_ROOT";
+
+    /**
+     * Extra containing a list of {@link Uri}s indicating temp files which the middleware is
+     * still using.
+     */
+    public static final String EXTRA_TEMP_FILES_IN_USE =
+            "android.telephony.mbms.extra.TEMP_FILES_IN_USE";
+
+    /**
+     * Extra containing a single {@link Uri} indicating the path to the temp file in which the
+     * decoded downloaded file resides. Must not be null.
+     */
+    public static final String EXTRA_FINAL_URI = "android.telephony.mbms.extra.FINAL_URI";
+
+    /**
+     * Extra containing a String representing a service ID, used by
+     * file-descriptor requests and cleanup requests to specify which service they want to
+     * request temp files or clean up temp files for, respectively.
+     */
+    public static final String EXTRA_SERVICE_ID =
+            "android.telephony.mbms.extra.SERVICE_ID";
+
+    /**
+     * Retrieves the {@link ComponentName} for the {@link android.content.BroadcastReceiver} that
+     * the various intents from the middleware should be targeted towards.
+     * @param packageName The package name of the app.
+     * @return The component name of the receiver that the middleware should send its intents to,
+     * or null if the app didn't declare it in the manifest.
+     */
+    public static ComponentName getAppReceiverFromPackageName(Context context, String packageName) {
+        ComponentName candidate = new ComponentName(packageName,
+                MbmsDownloadReceiver.class.getCanonicalName());
+        Intent queryIntent = new Intent();
+        queryIntent.setComponent(candidate);
+        List<ResolveInfo> receivers =
+                context.getPackageManager().queryBroadcastReceivers(queryIntent, 0);
+        if (receivers != null && receivers.size() > 0) {
+            return candidate;
+        }
+        return null;
+    }
+}
diff --git a/test-runner/Android.mk b/test-runner/Android.mk
index 3c3718a..060a518 100644
--- a/test-runner/Android.mk
+++ b/test-runner/Android.mk
@@ -107,11 +107,10 @@
 
 LOCAL_SOURCE_FILES_ALL_GENERATED := true
 
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
 # Make sure to run droiddoc first to generate the stub source files.
-$(full_classes_compiled_jar) : $(android_test_runner_api_gen_stamp)
-$(full_classes_jack) : $(android_test_runner_api_gen_stamp)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(android_test_runner_api_gen_stamp)
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
 
 # Archive a copy of the classes.jar in SDK build.
 $(call dist-for-goals,sdk win_sdk,$(full_classes_jar):android.test.runner.stubs.jar)
@@ -202,11 +201,10 @@
 
 LOCAL_SOURCE_FILES_ALL_GENERATED := true
 
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
 # Make sure to run droiddoc first to generate the stub source files.
-$(full_classes_compiled_jar) : $(android_test_mock_gen_stamp)
-$(full_classes_jack) : $(android_test_mock_gen_stamp)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(android_test_mock_gen_stamp)
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
 
 # Archive a copy of the classes.jar in SDK build.
 $(call dist-for-goals,sdk win_sdk,$(full_classes_jar):android.test.mock.stubs.jar)
diff --git a/tests/net/java/android/net/netlink/ConntrackMessageTest.java b/tests/net/java/android/net/netlink/ConntrackMessageTest.java
new file mode 100644
index 0000000..3aab942
--- /dev/null
+++ b/tests/net/java/android/net/netlink/ConntrackMessageTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2017 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.net.netlink;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assume.assumeTrue;
+
+import android.system.OsConstants;
+import libcore.util.HexEncoding;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ConntrackMessageTest {
+    private static final boolean USING_LE = (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN);
+
+    // Example 1: TCP (192.168.43.209, 44333) -> (23.211.13.26, 443)
+    public static final String CT_V4UPDATE_TCP_HEX =
+            // struct nlmsghdr
+            "50000000" +      // length = 80
+            "0001" +          // type = (1 << 8) | 0
+            "0501" +          // flags
+            "01000000" +      // seqno = 1
+            "00000000" +      // pid = 0
+            // struct nfgenmsg
+            "02" +            // nfgen_family  = AF_INET
+            "00" +            // version = NFNETLINK_V0
+            "0000" +          // res_id
+            // struct nlattr
+            "3400" +          // nla_len = 52
+            "0180" +          // nla_type = nested CTA_TUPLE_ORIG
+                // struct nlattr
+                "1400" +      // nla_len = 20
+                "0180" +      // nla_type = nested CTA_TUPLE_IP
+                    "0800 0100 C0A82BD1" +  // nla_type=CTA_IP_V4_SRC, ip=192.168.43.209
+                    "0800 0200 17D30D1A" +  // nla_type=CTA_IP_V4_DST, ip=23.211.13.26
+                // struct nlattr
+                "1C00" +      // nla_len = 28
+                "0280" +      // nla_type = nested CTA_TUPLE_PROTO
+                    "0500 0100 06 000000" +  // nla_type=CTA_PROTO_NUM, proto=6
+                    "0600 0200 AD2D 0000" +  // nla_type=CTA_PROTO_SRC_PORT, port=44333 (big endian)
+                    "0600 0300 01BB 0000" +  // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian)
+            // struct nlattr
+            "0800" +          // nla_len = 8
+            "0700" +          // nla_type = CTA_TIMEOUT
+            "00069780";       // nla_value = 432000 (big endian)
+    public static final byte[] CT_V4UPDATE_TCP_BYTES =
+            HexEncoding.decode(CT_V4UPDATE_TCP_HEX.replaceAll(" ", "").toCharArray(), false);
+
+    // Example 2: UDP (100.96.167.146, 37069) -> (216.58.197.10, 443)
+    public static final String CT_V4UPDATE_UDP_HEX =
+            // struct nlmsghdr
+            "50000000" +      // length = 80
+            "0001" +          // type = (1 << 8) | 0
+            "0501" +          // flags
+            "01000000" +      // seqno = 1
+            "00000000" +      // pid = 0
+            // struct nfgenmsg
+            "02" +            // nfgen_family  = AF_INET
+            "00" +            // version = NFNETLINK_V0
+            "0000" +          // res_id
+            // struct nlattr
+            "3400" +          // nla_len = 52
+            "0180" +          // nla_type = nested CTA_TUPLE_ORIG
+                // struct nlattr
+                "1400" +      // nla_len = 20
+                "0180" +      // nla_type = nested CTA_TUPLE_IP
+                    "0800 0100 6460A792" +  // nla_type=CTA_IP_V4_SRC, ip=100.96.167.146
+                    "0800 0200 D83AC50A" +  // nla_type=CTA_IP_V4_DST, ip=216.58.197.10
+                // struct nlattr
+                "1C00" +      // nla_len = 28
+                "0280" +      // nla_type = nested CTA_TUPLE_PROTO
+                    "0500 0100 11 000000" +  // nla_type=CTA_PROTO_NUM, proto=17
+                    "0600 0200 90CD 0000" +  // nla_type=CTA_PROTO_SRC_PORT, port=37069 (big endian)
+                    "0600 0300 01BB 0000" +  // nla_type=CTA_PROTO_DST_PORT, port=443 (big endian)
+            // struct nlattr
+            "0800" +          // nla_len = 8
+            "0700" +          // nla_type = CTA_TIMEOUT
+            "000000B4";       // nla_value = 180 (big endian)
+    public static final byte[] CT_V4UPDATE_UDP_BYTES =
+            HexEncoding.decode(CT_V4UPDATE_UDP_HEX.replaceAll(" ", "").toCharArray(), false);
+
+    @Test
+    public void testConntrackIPv4TcpTimeoutUpdate() throws Exception {
+        assumeTrue(USING_LE);
+
+        final byte[] tcp = ConntrackMessage.newIPv4TimeoutUpdateRequest(
+                OsConstants.IPPROTO_TCP,
+                (Inet4Address) InetAddress.getByName("192.168.43.209"), 44333,
+                (Inet4Address) InetAddress.getByName("23.211.13.26"), 443,
+                432000);
+        assertArrayEquals(CT_V4UPDATE_TCP_BYTES, tcp);
+    }
+
+    @Test
+    public void testConntrackIPv4UdpTimeoutUpdate() throws Exception {
+        assumeTrue(USING_LE);
+
+        final byte[] udp = ConntrackMessage.newIPv4TimeoutUpdateRequest(
+                OsConstants.IPPROTO_UDP,
+                (Inet4Address) InetAddress.getByName("100.96.167.146"), 37069,
+                (Inet4Address) InetAddress.getByName("216.58.197.10"), 443,
+                180);
+        assertArrayEquals(CT_V4UPDATE_UDP_BYTES, udp);
+    }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index f6481cf..8816d43 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -64,6 +64,7 @@
 import android.net.NetworkMisc;
 import android.net.NetworkRequest;
 import android.net.NetworkSpecifier;
+import android.net.NetworkUtils;
 import android.net.RouteInfo;
 import android.net.StringNetworkSpecifier;
 import android.net.metrics.IpConnectivityLog;
@@ -88,6 +89,7 @@
 import android.test.mock.MockContentResolver;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.TextUtils;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.LogPrinter;
 
@@ -109,7 +111,10 @@
 import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
@@ -304,6 +309,10 @@
         private String mRedirectUrl;
 
         MockNetworkAgent(int transport) {
+            this(transport, new LinkProperties());
+        }
+
+        MockNetworkAgent(int transport, LinkProperties linkProperties) {
             final int type = transportToLegacyType(transport);
             final String typeName = ConnectivityManager.getNetworkTypeName(type);
             mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
@@ -329,7 +338,7 @@
             mHandlerThread.start();
             mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
                     "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
-                    new LinkProperties(), mScore, new NetworkMisc()) {
+                    linkProperties, mScore, new NetworkMisc()) {
                 @Override
                 public void unwanted() { mDisconnected.open(); }
 
@@ -3338,6 +3347,68 @@
         assertException(() -> { mCm.requestRouteToHostAddress(TYPE_NONE, null); }, unsupported);
     }
 
+    @SmallTest
+    public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() {
+        final NetworkRequest networkRequest = new NetworkRequest.Builder()
+                .addTransportType(TRANSPORT_WIFI).build();
+        final TestNetworkCallback networkCallback = new TestNetworkCallback();
+        mCm.registerNetworkCallback(networkRequest, networkCallback);
+
+        LinkProperties lp = new LinkProperties();
+        lp.setInterfaceName("wlan0");
+        LinkAddress myIpv4Address = new LinkAddress("192.168.12.3/24");
+        RouteInfo myIpv4DefaultRoute = new RouteInfo((IpPrefix) null,
+                NetworkUtils.numericToInetAddress("192.168.12.1"), lp.getInterfaceName());
+        lp.addLinkAddress(myIpv4Address);
+        lp.addRoute(myIpv4DefaultRoute);
+
+        // Verify direct routes are added when network agent is first registered in
+        // ConnectivityService.
+        MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp);
+        networkAgent.connect(true);
+        networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent);
+        networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent);
+        CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
+                networkAgent);
+        networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
+        networkCallback.assertNoCallback();
+        checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address),
+                Arrays.asList(myIpv4DefaultRoute));
+        checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
+                Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
+
+        // Verify direct routes are added during subsequent link properties updates.
+        LinkProperties newLp = new LinkProperties(lp);
+        LinkAddress myIpv6Address1 = new LinkAddress("fe80::cafe/64");
+        LinkAddress myIpv6Address2 = new LinkAddress("2001:db8::2/64");
+        newLp.addLinkAddress(myIpv6Address1);
+        newLp.addLinkAddress(myIpv6Address2);
+        networkAgent.sendLinkProperties(newLp);
+        cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent);
+        networkCallback.assertNoCallback();
+        checkDirectlyConnectedRoutes(cbi.arg,
+                Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
+                Arrays.asList(myIpv4DefaultRoute));
+        mCm.unregisterNetworkCallback(networkCallback);
+    }
+
+    private void checkDirectlyConnectedRoutes(Object callbackObj,
+            Collection<LinkAddress> linkAddresses, Collection<RouteInfo> otherRoutes) {
+        assertTrue(callbackObj instanceof LinkProperties);
+        LinkProperties lp = (LinkProperties) callbackObj;
+
+        Set<RouteInfo> expectedRoutes = new ArraySet<>();
+        expectedRoutes.addAll(otherRoutes);
+        for (LinkAddress address : linkAddresses) {
+            RouteInfo localRoute = new RouteInfo(address, null, lp.getInterfaceName());
+            // Duplicates in linkAddresses are considered failures
+            assertTrue(expectedRoutes.add(localRoute));
+        }
+        List<RouteInfo> observedRoutes = lp.getRoutes();
+        assertEquals(expectedRoutes.size(), observedRoutes.size());
+        assertTrue(observedRoutes.containsAll(expectedRoutes));
+    }
+
     private static <T> void assertEmpty(T[] ts) {
         int length = ts.length;
         assertEquals("expected empty array, but length was " + length, 0, length);
diff --git a/tools/aapt/AaptXml.cpp b/tools/aapt/AaptXml.cpp
index b04a55d..6801a4e 100644
--- a/tools/aapt/AaptXml.cpp
+++ b/tools/aapt/AaptXml.cpp
@@ -99,24 +99,40 @@
     if (idx < 0) {
         return String8();
     }
+
     Res_value value;
-    if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
-        if (value.dataType == Res_value::TYPE_STRING) {
-            size_t len;
-            const char16_t* str = tree.getAttributeStringValue(idx, &len);
-            return str ? String8(str, len) : String8();
+    if (tree.getAttributeValue(idx, &value) == BAD_TYPE) {
+        if (outError != NULL) {
+            *outError = "attribute value is corrupt";
         }
-        resTable.resolveReference(&value, 0);
-        if (value.dataType != Res_value::TYPE_STRING) {
-            if (outError != NULL) {
-                *outError = "attribute is not a string value";
-            }
-            return String8();
-        }
+        return String8();
     }
+
+    // Check if the string is inline in the XML.
+    if (value.dataType == Res_value::TYPE_STRING) {
+        size_t len;
+        const char16_t* str = tree.getAttributeStringValue(idx, &len);
+        return str ? String8(str, len) : String8();
+    }
+
+    // Resolve the reference if there is one.
+    ssize_t block = resTable.resolveReference(&value, 0);
+    if (block < 0) {
+        if (outError != NULL) {
+            *outError = "attribute value reference does not exist";
+        }
+        return String8();
+    }
+
+    if (value.dataType != Res_value::TYPE_STRING) {
+        if (outError != NULL) {
+            *outError = "attribute is not a string value";
+        }
+        return String8();
+    }
+
     size_t len;
-    const Res_value* value2 = &value;
-    const char16_t* str = resTable.valueToString(value2, 0, NULL, &len);
+    const char16_t* str = resTable.valueToString(&value, static_cast<size_t>(block), NULL, &len);
     return str ? String8(str, len) : String8();
 }
 
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index 14d05fd..2ae2e49 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -92,7 +92,9 @@
         "flatten/XmlFlattener.cpp",
         "io/BigBufferStreams.cpp",
         "io/File.cpp",
+        "io/FileInputStream.cpp",
         "io/FileSystem.cpp",
+        "io/StringInputStream.cpp",
         "io/Util.cpp",
         "io/ZipArchive.cpp",
         "link/AutoVersioner.cpp",
@@ -140,7 +142,8 @@
         "xml/XmlDom.cpp",
         "xml/XmlPullParser.cpp",
         "xml/XmlUtil.cpp",
-        "Format.proto",
+        "Resources.proto",
+        "ResourcesInternal.proto",
     ],
     proto: {
         export_proto_headers: true,
@@ -164,6 +167,7 @@
 cc_test_host {
     name: "aapt2_tests",
     srcs: [
+        "test/Builders.cpp",
         "test/Common.cpp",
         "**/*_test.cpp",
     ],
diff --git a/tools/aapt2/ConfigDescription.cpp b/tools/aapt2/ConfigDescription.cpp
index 7ff0c72..a9278c1 100644
--- a/tools/aapt2/ConfigDescription.cpp
+++ b/tools/aapt2/ConfigDescription.cpp
@@ -70,7 +70,7 @@
 
 static bool parseMnc(const char* name, ResTable_config* out) {
   if (strcmp(name, kWildcardName) == 0) {
-    if (out) out->mcc = 0;
+    if (out) out->mnc = 0;
     return true;
   }
   const char* c = name;
@@ -967,8 +967,6 @@
                o.screenLayout & MASK_LAYOUTDIR) ||
          !pred(screenLayout & MASK_SCREENLONG,
                o.screenLayout & MASK_SCREENLONG) ||
-         !pred(screenLayout & MASK_UI_MODE_TYPE,
-               o.screenLayout & MASK_UI_MODE_TYPE) ||
          !pred(uiMode & MASK_UI_MODE_TYPE, o.uiMode & MASK_UI_MODE_TYPE) ||
          !pred(uiMode & MASK_UI_MODE_NIGHT, o.uiMode & MASK_UI_MODE_NIGHT) ||
          !pred(screenLayout2 & MASK_SCREENROUND,
diff --git a/tools/aapt2/ConfigDescription_test.cpp b/tools/aapt2/ConfigDescription_test.cpp
index 14a5656..1f351bf 100644
--- a/tools/aapt2/ConfigDescription_test.cpp
+++ b/tools/aapt2/ConfigDescription_test.cpp
@@ -140,4 +140,16 @@
   EXPECT_EQ(std::string("vrheadset-v26"), config.toString().string());
 }
 
+TEST(ConfigDescriptionTest, RangeQualifiersDoNotConflict) {
+  using test::ParseConfigOrDie;
+
+  EXPECT_FALSE(ParseConfigOrDie("large").ConflictsWith(ParseConfigOrDie("normal-land")));
+  EXPECT_FALSE(ParseConfigOrDie("long-hdpi").ConflictsWith(ParseConfigOrDie("xhdpi")));
+  EXPECT_FALSE(ParseConfigOrDie("sw600dp").ConflictsWith(ParseConfigOrDie("sw700dp")));
+  EXPECT_FALSE(ParseConfigOrDie("v11").ConflictsWith(ParseConfigOrDie("v21")));
+  EXPECT_FALSE(ParseConfigOrDie("h600dp").ConflictsWith(ParseConfigOrDie("h300dp")));
+  EXPECT_FALSE(ParseConfigOrDie("w400dp").ConflictsWith(ParseConfigOrDie("w300dp")));
+  EXPECT_FALSE(ParseConfigOrDie("600x400").ConflictsWith(ParseConfigOrDie("300x200")));
+}
+
 }  // namespace aapt
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp
index b872ebb..49ed778 100644
--- a/tools/aapt2/Debug.cpp
+++ b/tools/aapt2/Debug.cpp
@@ -33,6 +33,8 @@
 
 namespace aapt {
 
+namespace {
+
 class PrintVisitor : public ValueVisitor {
  public:
   using ValueVisitor::Visit;
@@ -88,9 +90,13 @@
     }
   }
 
-  void Visit(Array* array) override { array->Print(&std::cout); }
+  void Visit(Array* array) override {
+    array->Print(&std::cout);
+  }
 
-  void Visit(Plural* plural) override { plural->Print(&std::cout); }
+  void Visit(Plural* plural) override {
+    plural->Print(&std::cout);
+  }
 
   void Visit(Styleable* styleable) override {
     std::cout << "(styleable)";
@@ -110,11 +116,14 @@
     }
   }
 
-  void VisitItem(Item* item) override { item->Print(&std::cout); }
+  void VisitItem(Item* item) override {
+    item->Print(&std::cout);
+  }
 };
 
-void Debug::PrintTable(ResourceTable* table,
-                       const DebugPrintTableOptions& options) {
+}  // namespace
+
+void Debug::PrintTable(ResourceTable* table, const DebugPrintTableOptions& options) {
   PrintVisitor visitor;
 
   for (auto& package : table->packages) {
@@ -148,10 +157,9 @@
       }
 
       for (const ResourceEntry* entry : sorted_entries) {
-        ResourceId id(package->id ? package->id.value() : uint8_t(0),
-                      type->id ? type->id.value() : uint8_t(0),
-                      entry->id ? entry->id.value() : uint16_t(0));
-        ResourceName name(package->name, type->type, entry->name);
+        const ResourceId id(package->id.value_or_default(0), type->id.value_or_default(0),
+                            entry->id.value_or_default(0));
+        const ResourceName name(package->name, type->type, entry->name);
 
         std::cout << "    spec resource " << id << " " << name;
         switch (entry->symbol_status.state) {
@@ -180,16 +188,14 @@
   }
 }
 
-static size_t GetNodeIndex(const std::vector<ResourceName>& names,
-                           const ResourceName& name) {
+static size_t GetNodeIndex(const std::vector<ResourceName>& names, const ResourceName& name) {
   auto iter = std::lower_bound(names.begin(), names.end(), name);
   CHECK(iter != names.end());
   CHECK(*iter == name);
   return std::distance(names.begin(), iter);
 }
 
-void Debug::PrintStyleGraph(ResourceTable* table,
-                            const ResourceName& target_style) {
+void Debug::PrintStyleGraph(ResourceTable* table, const ResourceName& target_style) {
   std::map<ResourceName, std::set<ResourceName>> graph;
 
   std::queue<ResourceName> styles_to_visit;
@@ -223,8 +229,7 @@
 
   std::cout << "digraph styles {\n";
   for (const auto& name : names) {
-    std::cout << "  node_" << GetNodeIndex(names, name) << " [label=\"" << name
-              << "\"];\n";
+    std::cout << "  node_" << GetNodeIndex(names, name) << " [label=\"" << name << "\"];\n";
   }
 
   for (const auto& entry : graph) {
@@ -243,8 +248,7 @@
 void Debug::DumpHex(const void* data, size_t len) {
   const uint8_t* d = (const uint8_t*)data;
   for (size_t i = 0; i < len; i++) {
-    std::cerr << std::hex << std::setfill('0') << std::setw(2) << (uint32_t)d[i]
-              << " ";
+    std::cerr << std::hex << std::setfill('0') << std::setw(2) << (uint32_t)d[i] << " ";
     if (i % 8 == 7) {
       std::cerr << "\n";
     }
@@ -262,8 +266,15 @@
   using xml::Visitor::Visit;
 
   void Visit(xml::Element* el) override {
-    std::cerr << prefix_;
-    std::cerr << "E: ";
+    const size_t previous_size = prefix_.size();
+
+    for (const xml::NamespaceDecl& decl : el->namespace_decls) {
+      std::cerr << prefix_ << "N: " << decl.prefix << "=" << decl.uri
+                << " (line=" << decl.line_number << ")\n";
+      prefix_ += "  ";
+    }
+
+    std::cerr << prefix_ << "E: ";
     if (!el->namespace_uri.empty()) {
       std::cerr << el->namespace_uri << ":";
     }
@@ -283,26 +294,13 @@
       std::cerr << "=" << attr.value << "\n";
     }
 
-    const size_t previous_size = prefix_.size();
     prefix_ += "  ";
     xml::Visitor::Visit(el);
     prefix_.resize(previous_size);
   }
 
-  void Visit(xml::Namespace* ns) override {
-    std::cerr << prefix_;
-    std::cerr << "N: " << ns->namespace_prefix << "=" << ns->namespace_uri
-              << " (line=" << ns->line_number << ")\n";
-
-    const size_t previous_size = prefix_.size();
-    prefix_ += "  ";
-    xml::Visitor::Visit(ns);
-    prefix_.resize(previous_size);
-  }
-
   void Visit(xml::Text* text) override {
-    std::cerr << prefix_;
-    std::cerr << "T: '" << text->text << "'\n";
+    std::cerr << prefix_ << "T: '" << text->text << "'\n";
   }
 
  private:
diff --git a/tools/aapt2/Format.proto b/tools/aapt2/Format.proto
deleted file mode 100644
index 870b735..0000000
--- a/tools/aapt2/Format.proto
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-syntax = "proto2";
-
-option optimize_for = LITE_RUNTIME;
-
-package aapt.pb;
-
-message ConfigDescription {
-	optional bytes data = 1;
-	optional string product = 2;
-}
-
-message StringPool {
-	optional bytes data = 1;
-}
-
-message CompiledFile {
-	message Symbol {
-		optional string resource_name = 1;
-		optional uint32 line_no = 2;
-	}
-
-	optional string resource_name = 1;
-	optional ConfigDescription config = 2;
-	optional string source_path = 3;
-	repeated Symbol exported_symbols = 4;
-}
-
-message ResourceTable {
-	optional StringPool string_pool = 1;
-	optional StringPool source_pool = 2;
-	optional StringPool symbol_pool = 3;
-	repeated Package packages = 4;
-}
-
-message Package {
-	optional uint32 package_id = 1;
-	optional string package_name = 2;
-	repeated Type types = 3;
-}
-
-message Type {	
-	optional uint32 id = 1;
-	optional string name = 2;
-	repeated Entry entries = 3;
-}
-
-message SymbolStatus {
-	enum Visibility {
-		Unknown = 0;
-		Private = 1;
-		Public = 2;
-	}
-	optional Visibility visibility = 1;
-	optional Source source = 2;
-	optional string comment = 3;
-	optional bool allow_new = 4;
-}
-
-message Entry {
-	optional uint32 id = 1;
-	optional string name = 2;
-	optional SymbolStatus symbol_status = 3;
-	repeated ConfigValue config_values = 4;
-}
-
-message ConfigValue {
-	optional ConfigDescription config = 1;
-	optional Value value = 2;
-}
-
-message Source {
-	optional uint32 path_idx = 1;
-	optional uint32 line_no = 2;
-	optional uint32 col_no = 3;
-}
-
-message Reference {
-	enum Type {
-		Ref = 0;
-		Attr = 1;
-	}
-	optional Type type = 1;
-	optional uint32 id = 2;
-	optional uint32 symbol_idx = 3;
-	optional bool private = 4;
-}
-
-message Id {
-}
-
-message String {
-	optional uint32 idx = 1;
-}
-
-message RawString {
-	optional uint32 idx = 1;
-}
-
-message FileReference {
-	optional uint32 path_idx = 1;
-}
-
-message Primitive {
-	optional uint32 type = 1;
-	optional uint32 data = 2;
-}
-
-message Attribute {
-	message Symbol {
-		optional Source source = 1;
-		optional string comment = 2;
-		optional Reference name = 3;
-		optional uint32 value = 4;
-	}
-	optional uint32 format_flags = 1;
-	optional int32 min_int = 2;
-	optional int32 max_int = 3;
-	repeated Symbol symbols = 4;
-}
-
-message Style {
-	message Entry {
-		optional Source source = 1;
-		optional string comment = 2;
-		optional Reference key = 3;
-		optional Item item = 4;
-	}
-
-	optional Reference parent = 1;
-	optional Source parent_source = 2;
-	repeated Entry entries = 3;
-}
-
-message Styleable {
-	message Entry {
-		optional Source source = 1;
-		optional string comment = 2;
-		optional Reference attr = 3;
-	}
-	repeated Entry entries = 1;
-}
-
-message Array {
-	message Entry {
-		optional Source source = 1;
-		optional string comment = 2;
-		optional Item item = 3;
-	}
-	repeated Entry entries = 1;
-}
-
-message Plural {
-	enum Arity {
-		Zero = 0;
-		One = 1;
-		Two = 2;
-		Few = 3;
-		Many = 4;
-		Other = 5;
-	}
-		
-	message Entry {
-		optional Source source = 1;
-		optional string comment = 2;
-		optional Arity arity = 3;
-		optional Item item = 4;
-	}
-	repeated Entry entries = 1;
-}
-
-message Item {
-	optional Reference ref = 1;
-	optional String str = 2;
-	optional RawString raw_str = 3;
-	optional FileReference file = 4;
-	optional Id id = 5;
-	optional Primitive prim = 6;
-}
-
-message CompoundValue {
-	optional Attribute attr = 1;
-	optional Style style = 2;
-	optional Styleable styleable = 3;
-	optional Array array = 4;
-	optional Plural plural = 5;
-}
-
-message Value {
-	optional Source source = 1;
-	optional string comment = 2;
-	optional bool weak = 3;
-	
-	optional Item item = 4;
-	optional CompoundValue compound_value = 5;	
-}
diff --git a/tools/aapt2/Main.cpp b/tools/aapt2/Main.cpp
index c5d38ab..36ab30c 100644
--- a/tools/aapt2/Main.cpp
+++ b/tools/aapt2/Main.cpp
@@ -14,12 +14,26 @@
  * limitations under the License.
  */
 
+#ifdef _WIN32
+// clang-format off
+#include <windows.h>
+#include <shellapi.h>
+// clang-format on
+#endif
+
 #include <iostream>
 #include <vector>
 
+#include "android-base/stringprintf.h"
+#include "android-base/utf8.h"
 #include "androidfw/StringPiece.h"
 
 #include "Diagnostics.h"
+#include "util/Files.h"
+#include "util/Util.h"
+
+using ::android::StringPiece;
+using ::android::base::StringPrintf;
 
 namespace aapt {
 
@@ -27,54 +41,136 @@
 static const char* sMajorVersion = "2";
 
 // Update minor version whenever a feature or flag is added.
-static const char* sMinorVersion = "18";
+static const char* sMinorVersion = "19";
 
-int PrintVersion() {
-  std::cerr << "Android Asset Packaging Tool (aapt) " << sMajorVersion << "."
-            << sMinorVersion << std::endl;
-  return 0;
+static void PrintVersion() {
+  std::cerr << StringPrintf("Android Asset Packaging Tool (aapt) %s:%s", sMajorVersion,
+                            sMinorVersion)
+            << std::endl;
 }
 
-extern int Compile(const std::vector<android::StringPiece>& args, IDiagnostics* diagnostics);
-extern int Link(const std::vector<android::StringPiece>& args, IDiagnostics* diagnostics);
-extern int Dump(const std::vector<android::StringPiece>& args);
-extern int Diff(const std::vector<android::StringPiece>& args);
-extern int Optimize(const std::vector<android::StringPiece>& args);
+static void PrintUsage() {
+  std::cerr << "\nusage: aapt2 [compile|link|dump|diff|optimize|version] ..." << std::endl;
+}
+
+extern int Compile(const std::vector<StringPiece>& args, IDiagnostics* diagnostics);
+extern int Link(const std::vector<StringPiece>& args, IDiagnostics* diagnostics);
+extern int Dump(const std::vector<StringPiece>& args);
+extern int Diff(const std::vector<StringPiece>& args);
+extern int Optimize(const std::vector<StringPiece>& args);
+
+static int ExecuteCommand(const StringPiece& command, const std::vector<StringPiece>& args,
+                          IDiagnostics* diagnostics) {
+  if (command == "compile" || command == "c") {
+    return Compile(args, diagnostics);
+  } else if (command == "link" || command == "l") {
+    return Link(args, diagnostics);
+  } else if (command == "dump" || command == "d") {
+    return Dump(args);
+  } else if (command == "diff") {
+    return Diff(args);
+  } else if (command == "optimize") {
+    return Optimize(args);
+  } else if (command == "version") {
+    PrintVersion();
+    return 0;
+  }
+  diagnostics->Error(DiagMessage() << "unknown command '" << command << "'");
+  return -1;
+}
+
+static void RunDaemon(IDiagnostics* diagnostics) {
+  std::cout << "Ready" << std::endl;
+
+  // Run in daemon mode. The first line of input is the command. This can be 'quit' which ends
+  // the daemon mode. Each subsequent line is a single parameter to the command. The end of a
+  // invocation is signaled by providing an empty line. At any point, an EOF signal or the
+  // command 'quit' will end the daemon mode.
+  while (true) {
+    std::vector<std::string> raw_args;
+    for (std::string line; std::getline(std::cin, line) && !line.empty();) {
+      raw_args.push_back(line);
+    }
+
+    if (!std::cin) {
+      break;
+    }
+
+    // An empty command does nothing.
+    if (raw_args.empty()) {
+      continue;
+    }
+
+    if (raw_args[0] == "quit") {
+      break;
+    }
+
+    std::vector<StringPiece> args;
+    args.insert(args.end(), ++raw_args.begin(), raw_args.end());
+    int ret = ExecuteCommand(raw_args[0], args, diagnostics);
+    if (ret != 0) {
+      std::cerr << "Error" << std::endl;
+    }
+    std::cerr << "Done" << std::endl;
+  }
+  std::cout << "Exiting daemon" << std::endl;
+}
 
 }  // namespace aapt
 
-int main(int argc, char** argv) {
-  if (argc >= 2) {
-    argv += 1;
-    argc -= 1;
-
-    std::vector<android::StringPiece> args;
-    for (int i = 1; i < argc; i++) {
-      args.push_back(argv[i]);
-    }
-
-    android::StringPiece command(argv[0]);
-    if (command == "compile" || command == "c") {
-      aapt::StdErrDiagnostics diagnostics;
-      return aapt::Compile(args, &diagnostics);
-    } else if (command == "link" || command == "l") {
-      aapt::StdErrDiagnostics diagnostics;
-      return aapt::Link(args, &diagnostics);
-    } else if (command == "dump" || command == "d") {
-      return aapt::Dump(args);
-    } else if (command == "diff") {
-      return aapt::Diff(args);
-    } else if (command == "optimize") {
-      return aapt::Optimize(args);
-    } else if (command == "version") {
-      return aapt::PrintVersion();
-    }
-    std::cerr << "unknown command '" << command << "'\n";
-  } else {
+int MainImpl(int argc, char** argv) {
+  if (argc < 2) {
     std::cerr << "no command specified\n";
+    aapt::PrintUsage();
+    return -1;
   }
 
-  std::cerr << "\nusage: aapt2 [compile|link|dump|diff|optimize|version] ..."
-            << std::endl;
-  return 1;
+  argv += 1;
+  argc -= 1;
+
+  aapt::StdErrDiagnostics diagnostics;
+
+  // Collect the arguments starting after the program name and command name.
+  std::vector<StringPiece> args;
+  for (int i = 1; i < argc; i++) {
+    args.push_back(argv[i]);
+  }
+
+  const StringPiece command(argv[0]);
+  if (command != "daemon" && command != "m") {
+    // Single execution.
+    const int result = aapt::ExecuteCommand(command, args, &diagnostics);
+    if (result < 0) {
+      aapt::PrintUsage();
+    }
+    return result;
+  }
+
+  aapt::RunDaemon(&diagnostics);
+  return 0;
+}
+
+int main(int argc, char** argv) {
+#ifdef _WIN32
+  LPWSTR* wide_argv = CommandLineToArgvW(GetCommandLineW(), &argc);
+  CHECK(wide_argv != nullptr) << "invalid command line parameters passed to process";
+
+  std::vector<std::string> utf8_args;
+  for (int i = 0; i < argc; i++) {
+    std::string utf8_arg;
+    if (!::android::base::WideToUTF8(wide_argv[i], &utf8_arg)) {
+      std::cerr << "error converting input arguments to UTF-8" << std::endl;
+      return 1;
+    }
+    utf8_args.push_back(std::move(utf8_arg));
+  }
+  LocalFree(wide_argv);
+
+  std::unique_ptr<char* []> utf8_argv(new char*[utf8_args.size()]);
+  for (int i = 0; i < argc; i++) {
+    utf8_argv[i] = const_cast<char*>(utf8_args[i].c_str());
+  }
+  argv = utf8_argv.get();
+#endif
+  return MainImpl(argc, argv);
 }
diff --git a/tools/aapt2/Resource.cpp b/tools/aapt2/Resource.cpp
index 35971e7..a9f5f29 100644
--- a/tools/aapt2/Resource.cpp
+++ b/tools/aapt2/Resource.cpp
@@ -61,6 +61,8 @@
       return "menu";
     case ResourceType::kMipmap:
       return "mipmap";
+    case ResourceType::kNavigation:
+      return "navigation";
     case ResourceType::kPlurals:
       return "plurals";
     case ResourceType::kRaw:
@@ -98,6 +100,7 @@
     {"layout", ResourceType::kLayout},
     {"menu", ResourceType::kMenu},
     {"mipmap", ResourceType::kMipmap},
+    {"navigation", ResourceType::kNavigation},
     {"plurals", ResourceType::kPlurals},
     {"raw", ResourceType::kRaw},
     {"string", ResourceType::kString},
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index 0a74c1a..cbcc8fb 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -59,6 +59,7 @@
   kLayout,
   kMenu,
   kMipmap,
+  kNavigation,
   kPlurals,
   kRaw,
   kString,
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index a5783a5..1c3ac2a 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -1219,7 +1219,7 @@
         continue;
       }
       item->SetSource(item_source);
-      array->items.emplace_back(std::move(item));
+      array->elements.emplace_back(std::move(item));
 
     } else if (!ShouldIgnoreElement(element_namespace, element_name)) {
       diag_->Error(DiagMessage(source_.WithLine(parser->line_number()))
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index 1683c64..144ebd2 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -22,9 +22,11 @@
 #include "ResourceTable.h"
 #include "ResourceUtils.h"
 #include "ResourceValues.h"
+#include "io/StringInputStream.h"
 #include "test/Test.h"
 #include "xml/XmlPullParser.h"
 
+using ::aapt::io::StringInputStream;
 using ::aapt::test::StrValueEq;
 using ::aapt::test::ValueEq;
 using ::android::ResTable_map;
@@ -43,11 +45,13 @@
 
 TEST(ResourceParserSingleTest, FailToParseWithNoRootResourcesElement) {
   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
-  std::stringstream input(kXmlPreamble);
-  input << R"(<attr name="foo"/>)" << std::endl;
   ResourceTable table;
   ResourceParser parser(context->GetDiagnostics(), &table, Source{"test"}, {});
-  xml::XmlPullParser xml_parser(input);
+
+  std::string input = kXmlPreamble;
+  input += R"(<attr name="foo"/>)";
+  StringInputStream in(input);
+  xml::XmlPullParser xml_parser(&in);
   ASSERT_FALSE(parser.Parse(&xml_parser));
 }
 
@@ -62,12 +66,16 @@
   }
 
   ::testing::AssertionResult TestParse(const StringPiece& str, const ConfigDescription& config) {
-    std::stringstream input(kXmlPreamble);
-    input << "<resources>\n" << str << "\n</resources>" << std::endl;
     ResourceParserOptions parserOptions;
     ResourceParser parser(context_->GetDiagnostics(), &table_, Source{"test"}, config,
                           parserOptions);
-    xml::XmlPullParser xmlParser(input);
+
+    std::string input = kXmlPreamble;
+    input += "<resources>\n";
+    input.append(str.data(), str.size());
+    input += "\n</resources>";
+    StringInputStream in(input);
+    xml::XmlPullParser xmlParser(&in);
     if (parser.Parse(&xmlParser)) {
       return ::testing::AssertionSuccess();
     }
@@ -532,11 +540,11 @@
 
   Array* array = test::GetValue<Array>(&table_, "array/foo");
   ASSERT_THAT(array, NotNull());
-  ASSERT_THAT(array->items, SizeIs(3));
+  ASSERT_THAT(array->elements, SizeIs(3));
 
-  EXPECT_THAT(ValueCast<Reference>(array->items[0].get()), NotNull());
-  EXPECT_THAT(ValueCast<String>(array->items[1].get()), NotNull());
-  EXPECT_THAT(ValueCast<BinaryPrimitive>(array->items[2].get()), NotNull());
+  EXPECT_THAT(ValueCast<Reference>(array->elements[0].get()), NotNull());
+  EXPECT_THAT(ValueCast<String>(array->elements[1].get()), NotNull());
+  EXPECT_THAT(ValueCast<BinaryPrimitive>(array->elements[2].get()), NotNull());
 }
 
 TEST_F(ResourceParserTest, ParseStringArray) {
@@ -557,9 +565,9 @@
 
   Array* array = test::GetValue<Array>(&table_, "array/foo");
   ASSERT_THAT(array, NotNull());
-  ASSERT_THAT(array->items, SizeIs(1));
+  ASSERT_THAT(array->elements, SizeIs(1));
 
-  String* str = ValueCast<String>(array->items[0].get());
+  String* str = ValueCast<String>(array->elements[0].get());
   ASSERT_THAT(str, NotNull());
   EXPECT_THAT(*str, StrValueEq("100"));
 }
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp
index eb59175..1cba194 100644
--- a/tools/aapt2/ResourceValues.cpp
+++ b/tools/aapt2/ResourceValues.cpp
@@ -805,13 +805,12 @@
     return false;
   }
 
-  if (items.size() != other->items.size()) {
+  if (elements.size() != other->elements.size()) {
     return false;
   }
 
-  return std::equal(items.begin(), items.end(), other->items.begin(),
-                    [](const std::unique_ptr<Item>& a,
-                       const std::unique_ptr<Item>& b) -> bool {
+  return std::equal(elements.begin(), elements.end(), other->elements.begin(),
+                    [](const std::unique_ptr<Item>& a, const std::unique_ptr<Item>& b) -> bool {
                       return a->Equals(b.get());
                     });
 }
@@ -820,14 +819,14 @@
   Array* array = new Array();
   array->comment_ = comment_;
   array->source_ = source_;
-  for (auto& item : items) {
-    array->items.emplace_back(std::unique_ptr<Item>(item->Clone(new_pool)));
+  for (auto& item : elements) {
+    array->elements.emplace_back(std::unique_ptr<Item>(item->Clone(new_pool)));
   }
   return array;
 }
 
 void Array::Print(std::ostream* out) const {
-  *out << "(array) [" << util::Joiner(items, ", ") << "]";
+  *out << "(array) [" << util::Joiner(elements, ", ") << "]";
 }
 
 bool Plural::Equals(const Value* value) const {
diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h
index 7e7547f..275864b 100644
--- a/tools/aapt2/ResourceValues.h
+++ b/tools/aapt2/ResourceValues.h
@@ -292,7 +292,7 @@
 };
 
 struct Array : public BaseValue<Array> {
-  std::vector<std::unique_ptr<Item>> items;
+  std::vector<std::unique_ptr<Item>> elements;
 
   bool Equals(const Value* value) const override;
   Array* Clone(StringPool* new_pool) const override;
diff --git a/tools/aapt2/ResourceValues_test.cpp b/tools/aapt2/ResourceValues_test.cpp
index 06c3404..10f9b55 100644
--- a/tools/aapt2/ResourceValues_test.cpp
+++ b/tools/aapt2/ResourceValues_test.cpp
@@ -54,19 +54,19 @@
   StringPool pool;
 
   Array a;
-  a.items.push_back(util::make_unique<String>(pool.MakeRef("one")));
-  a.items.push_back(util::make_unique<String>(pool.MakeRef("two")));
+  a.elements.push_back(util::make_unique<String>(pool.MakeRef("one")));
+  a.elements.push_back(util::make_unique<String>(pool.MakeRef("two")));
 
   Array b;
-  b.items.push_back(util::make_unique<String>(pool.MakeRef("une")));
-  b.items.push_back(util::make_unique<String>(pool.MakeRef("deux")));
+  b.elements.push_back(util::make_unique<String>(pool.MakeRef("une")));
+  b.elements.push_back(util::make_unique<String>(pool.MakeRef("deux")));
 
   Array c;
-  c.items.push_back(util::make_unique<String>(pool.MakeRef("uno")));
+  c.elements.push_back(util::make_unique<String>(pool.MakeRef("uno")));
 
   Array d;
-  d.items.push_back(util::make_unique<String>(pool.MakeRef("one")));
-  d.items.push_back(util::make_unique<String>(pool.MakeRef("two")));
+  d.elements.push_back(util::make_unique<String>(pool.MakeRef("one")));
+  d.elements.push_back(util::make_unique<String>(pool.MakeRef("two")));
 
   EXPECT_FALSE(a.Equals(&b));
   EXPECT_FALSE(a.Equals(&c));
@@ -78,8 +78,8 @@
   StringPool pool;
 
   Array a;
-  a.items.push_back(util::make_unique<String>(pool.MakeRef("one")));
-  a.items.push_back(util::make_unique<String>(pool.MakeRef("two")));
+  a.elements.push_back(util::make_unique<String>(pool.MakeRef("one")));
+  a.elements.push_back(util::make_unique<String>(pool.MakeRef("two")));
 
   std::unique_ptr<Array> b(a.Clone(&pool));
   EXPECT_TRUE(a.Equals(b.get()));
diff --git a/tools/aapt2/Resource_test.cpp b/tools/aapt2/Resource_test.cpp
index ad4e3ce..c557f3c 100644
--- a/tools/aapt2/Resource_test.cpp
+++ b/tools/aapt2/Resource_test.cpp
@@ -93,6 +93,10 @@
   ASSERT_NE(type, nullptr);
   EXPECT_EQ(*type, ResourceType::kMipmap);
 
+  type = ParseResourceType("navigation");
+  ASSERT_NE(type, nullptr);
+  EXPECT_EQ(*type, ResourceType::kNavigation);
+
   type = ParseResourceType("plurals");
   ASSERT_NE(type, nullptr);
   EXPECT_EQ(*type, ResourceType::kPlurals);
diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto
new file mode 100644
index 0000000..71f33b0
--- /dev/null
+++ b/tools/aapt2/Resources.proto
@@ -0,0 +1,471 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+// Keep proto2 syntax because we require the distinction between fields that
+// are set and unset.
+syntax = "proto2";
+
+option java_package = "com.android.aapt";
+option optimize_for = LITE_RUNTIME;
+
+package aapt.pb;
+
+// A configuration description that wraps the binary form of the C++ class
+// aapt::ConfigDescription, with an added product definition.
+// TODO(adamlesinski): Flesh this out to be represented in proto.
+message ConfigDescription {
+  optional bytes data = 1;
+  optional string product = 2;
+}
+
+// A string pool that wraps the binary form of the C++ class android::ResStringPool.
+message StringPool {
+  optional bytes data = 1;
+}
+
+// The position of a declared entity within a file.
+message SourcePosition {
+  optional uint32 line_number = 1;
+  optional uint32 column_number = 2;
+}
+
+// Developer friendly source file information for an entity in the resource table.
+message Source {
+  // The index of the string path within the source string pool of a ResourceTable.
+  optional uint32 path_idx = 1;
+  optional SourcePosition position = 2;
+}
+
+// Top level message representing a resource table.
+message ResourceTable {
+  // The string pool containing source paths referenced throughout the resource table. This does
+  // not end up in the final binary ARSC file.
+  optional StringPool source_pool = 1;
+
+  // Resource definitions corresponding to an Android package.
+  repeated Package package = 2;
+}
+
+// Defines resources for an Android package.
+message Package {
+  // The package ID of this package, in the range [0x00, 0xff].
+  // The ID 0x00 is reserved for shared libraries, or when the ID is assigned at run-time.
+  // The ID 0x01 is reserved for the 'android' package (framework).
+  // The ID range [0x02, 0x7f) is reserved for auto-assignment to shared libraries at run-time.
+  // The ID 0x7f is reserved for the application package.
+  // IDs > 0x7f are reserved for the application as well and are treated as feature splits.
+  optional uint32 package_id = 1;
+
+  // The Java compatible Android package name of the app.
+  optional string package_name = 2;
+
+  // The series of types defined by the package.
+  repeated Type type = 3;
+}
+
+// A set of resources grouped under a common type. Such types include string, layout, xml, dimen,
+// attr, etc. This maps to the second part of a resource identifier in Java (R.type.entry).
+message Type {
+  // The ID of the type. This may be 0, which indicates no ID is set.
+  optional uint32 id = 1;
+
+  // The name of the type. This corresponds to the 'type' part of a full resource name of the form
+  // package:type/entry. The set of legal type names is listed in Resource.cpp.
+  optional string name = 2;
+
+  // The entries defined for this type.
+  repeated Entry entry = 3;
+}
+
+// The status of a symbol/entry. This contains information like visibility (public/private),
+// comments, and whether the entry can be overridden.
+message SymbolStatus {
+  // The visibility of the resource outside of its package.
+  enum Visibility {
+    // No visibility was explicitly specified. This is typically treated as private.
+    // The distinction is important when two separate R.java files are generated: a public and
+    // private one. An unknown visibility, in this case, would cause the resource to be omitted
+    // from either R.java.
+    UNKNOWN = 0;
+
+    // A resource was explicitly marked as private. This means the resource can not be accessed
+    // outside of its package unless the @*package:type/entry notation is used (the asterisk being
+    // the private accessor). If two R.java files are generated (private + public), the resource
+    // will only be emitted to the private R.java file.
+    PRIVATE = 1;
+
+    // A resource was explicitly marked as public. This means the resource can be accessed
+    // from any package, and is emitted into all R.java files, public and private.
+    PUBLIC = 2;
+  }
+
+  optional Visibility visibility = 1;
+
+  // The path at which this entry's visibility was defined (eg. public.xml).
+  optional Source source = 2;
+
+  // The comment associated with the <public> tag.
+  optional string comment = 3;
+
+  // Whether the symbol can be merged into another resource table without there being an existing
+  // definition to override. Used for overlays and set to true when <add-resource> is specified.
+  optional bool allow_new = 4;
+}
+
+// An entry declaration. An entry has a full resource ID that is the combination of package ID,
+// type ID, and its own entry ID. An entry on its own has no value, but values are defined for
+// various configurations/variants.
+message Entry {
+  // The ID of this entry. Together with the package ID and type ID, this forms a full resource ID
+  // of the form 0xPPTTEEEE, where PP is the package ID, TT is the type ID, and EEEE is the entry
+  // ID.
+  optional uint32 id = 1;
+
+  // The name of this entry. This corresponds to the 'entry' part of a full resource name of the
+  // form package:type/entry.
+  optional string name = 2;
+
+  // The symbol status of this entry, which includes visibility information.
+  optional SymbolStatus symbol_status = 3;
+
+  // The set of values defined for this entry, each corresponding to a different
+  // configuration/variant.
+  repeated ConfigValue config_value = 4;
+}
+
+// A Configuration/Value pair.
+message ConfigValue {
+  optional ConfigDescription config = 1;
+  optional Value value = 2;
+}
+
+// The generic meta-data for every value in a resource table.
+message Value {
+  // Where the value was defined.
+  optional Source source = 1;
+
+  // Any comment associated with the value.
+  optional string comment = 2;
+
+  // Whether the value can be overridden.
+  optional bool weak = 3;
+
+  // If the value is an Item, this is set.
+  optional Item item = 4;
+
+  // If the value is a CompoundValue, this is set.
+  optional CompoundValue compound_value = 5;
+}
+
+// An Item is an abstract type. It represents a value that can appear inline in many places, such
+// as XML attribute values or on the right hand side of style attribute definitions. The concrete
+// type is one of the types below. Only one can be set.
+message Item {
+  optional Reference ref = 1;
+  optional String str = 2;
+  optional RawString raw_str = 3;
+  optional StyledString styled_str = 4;
+  optional FileReference file = 5;
+  optional Id id = 6;
+  optional Primitive prim = 7;
+}
+
+// A CompoundValue is an abstract type. It represents a value that is a made of other values.
+// These can only usually appear as top-level resources. The concrete type is one of the types
+// below. Only one can be set.
+message CompoundValue {
+  optional Attribute attr = 1;
+  optional Style style = 2;
+  optional Styleable styleable = 3;
+  optional Array array = 4;
+  optional Plural plural = 5;
+}
+
+// A value that is a reference to another resource. This reference can be by name or resource ID.
+message Reference {
+  enum Type {
+    // A plain reference (@package:type/entry).
+    REFERENCE = 0;
+
+    // A reference to a theme attribute (?package:type/entry).
+    ATTRIBUTE = 1;
+  }
+
+  optional Type type = 1;
+
+  // The resource ID (0xPPTTEEEE) of the resource being referred.
+  optional uint32 id = 2;
+
+  // The optional resource name.
+  optional string name = 3;
+
+  // Whether this reference is referencing a private resource (@*package:type/entry).
+  optional bool private = 4;
+}
+
+// A value that represents an ID. This is just a placeholder, as ID values are used to occupy a
+// resource ID (0xPPTTEEEE) as a unique identifier. Their value is unimportant.
+message Id {
+}
+
+// A value that is a string.
+message String {
+  optional string value = 1;
+}
+
+// A value that is a raw string, which is unescaped/uninterpreted. This is typically used to
+// represent the value of a style attribute before the attribute is compiled and the set of
+// allowed values is known.
+message RawString {
+  optional string value = 1;
+}
+
+// A string with styling information, like html tags that specify boldness, italics, etc.
+message StyledString {
+  // The raw text of the string.
+  optional string value = 1;
+
+  // A Span marks a region of the string text that is styled.
+  message Span {
+    // The name of the tag, and its attributes, encoded as follows:
+    // tag_name;attr1=value1;attr2=value2;[...]
+    optional string tag = 1;
+
+    // The first character position this span applies to, in UTF-16 offset.
+    optional uint32 first_char = 2;
+
+    // The last character position this span applies to, in UTF-16 offset.
+    optional uint32 last_char = 3;
+  }
+
+  repeated Span span = 2;
+}
+
+// A value that is a reference to an external entity, like an XML file or a PNG.
+message FileReference {
+  // Path to a file within the APK (typically res/type-config/entry.ext).
+  optional string path = 1;
+}
+
+// A value that represents a primitive data type (float, int, boolean, etc.).
+// Corresponds to the fields (type/data) of the C struct android::Res_value.
+message Primitive {
+  optional uint32 type = 1;
+  optional uint32 data = 2;
+}
+
+// A value that represents an XML attribute and what values it accepts.
+message Attribute {
+  // A Symbol used to represent an enum or a flag.
+  message Symbol {
+    // Where the enum/flag item was defined.
+    optional Source source = 1;
+
+    // Any comments associated with the enum or flag.
+    optional string comment = 2;
+
+    // The name of the enum/flag as a reference. Enums/flag items are generated as ID resource
+    // values.
+    optional Reference name = 3;
+
+    // The value of the enum/flag.
+    optional uint32 value = 4;
+  }
+
+  // Bitmask of formats allowed for an attribute.
+  enum FormatFlags {
+    ANY = 0x0000ffff;    // Allows any type except ENUM and FLAGS.
+    REFERENCE = 0x01;    // Allows Reference values.
+    STRING = 0x02;       // Allows String/StyledString values.
+    INTEGER = 0x04;      // Allows any integer BinaryPrimitive values.
+    BOOLEAN = 0x08;      // Allows any boolean BinaryPrimitive values.
+    COLOR = 0x010;       // Allows any color BinaryPrimitive values.
+    FLOAT = 0x020;       // Allows any float BinaryPrimitive values.
+    DIMENSION = 0x040;   // Allows any dimension BinaryPrimitive values.
+    FRACTION = 0x080;    // Allows any fraction BinaryPrimitive values.
+    ENUM = 0x00010000;   // Allows enums that are defined in the Attribute's symbols.
+                         // ENUM and FLAGS cannot BOTH be set.
+    FLAGS = 0x00020000;  // Allows flags that are defined in the Attribute's symbols.
+                         // ENUM and FLAGS cannot BOTH be set.
+  }
+
+  // A bitmask of types that this XML attribute accepts. Corresponds to the flags in the
+  // enum FormatFlags.
+  optional uint32 format_flags = 1;
+
+  // The smallest integer allowed for this XML attribute. Only makes sense if the format includes
+  // FormatFlags::INTEGER.
+  optional int32 min_int = 2;
+
+  // The largest integer allowed for this XML attribute. Only makes sense if the format includes
+  // FormatFlags::INTEGER.
+  optional int32 max_int = 3;
+
+  // The set of enums/flags defined in this attribute. Only makes sense if the format includes
+  // either FormatFlags::ENUM or FormatFlags::FLAGS. Having both is an error.
+  repeated Symbol symbol = 4;
+}
+
+// A value that represents a style.
+message Style {
+  // An XML attribute/value pair defined in the style.
+  message Entry {
+    // Where the entry was defined.
+    optional Source source = 1;
+
+    // Any comments associated with the entry.
+    optional string comment = 2;
+
+    // A reference to the XML attribute.
+    optional Reference key = 3;
+
+    // The Item defined for this XML attribute.
+    optional Item item = 4;
+  }
+
+  // The optinal style from which this style inherits attributes.
+  optional Reference parent = 1;
+
+  // The source file information of the parent inheritance declaration.
+  optional Source parent_source = 2;
+
+  // The set of XML attribute/value pairs for this style.
+  repeated Entry entry = 3;
+}
+
+// A value that represents a <declare-styleable> XML resource. These are not real resources and
+// only end up as Java fields in the generated R.java. They do not end up in the binary ARSC file.
+message Styleable {
+  // An attribute defined for this styleable.
+  message Entry {
+    // Where the attribute was defined within the <declare-styleable> block.
+    optional Source source = 1;
+
+    // Any comments associated with the declaration.
+    optional string comment = 2;
+
+    // The reference to the attribute.
+    optional Reference attr = 3;
+  }
+
+  // The set of attribute declarations.
+  repeated Entry entry = 1;
+}
+
+// A value that represents an array of resource values.
+message Array {
+  // A single element of the array.
+  message Element {
+    // Where the element was defined.
+    optional Source source = 1;
+
+    // Any comments associated with the element.
+    optional string comment = 2;
+
+    // The value assigned to this element.
+    optional Item item = 3;
+  }
+
+  // The list of array elements.
+  repeated Element element = 1;
+}
+
+// A value that represents a string and its many variations based on plurality.
+message Plural {
+  // The arity of the plural.
+  enum Arity {
+    ZERO = 0;
+    ONE = 1;
+    TWO = 2;
+    FEW = 3;
+    MANY = 4;
+    OTHER = 5;
+  }
+
+  // The plural value for a given arity.
+  message Entry {
+    // Where the plural was defined.
+    optional Source source = 1;
+
+    // Any comments associated with the plural.
+    optional string comment = 2;
+
+    // The arity of the plural.
+    optional Arity arity = 3;
+
+    // The value assigned to this plural.
+    optional Item item = 4;
+  }
+
+  // The set of arity/plural mappings.
+  repeated Entry entry = 1;
+}
+
+// Defines an abstract XmlNode that must be either an XmlElement, or
+// a text node represented by a string.
+message XmlNode {
+  // If set, this node is an element/tag.
+  optional XmlElement element = 1;
+
+  // If set, this node is a chunk of text.
+  optional string text = 2;
+
+  // Source line and column info.
+  optional SourcePosition source = 3;
+}
+
+// An <element> in an XML document.
+message XmlElement {
+  // Namespaces defined on this element.
+  repeated XmlNamespace namespace_declaration = 1;
+
+  // The namespace URI of this element.
+  optional string namespace_uri = 2;
+
+  // The name of this element.
+  optional string name = 3;
+
+  // The attributes of this element.
+  repeated XmlAttribute attribute = 4;
+
+  // The children of this element.
+  repeated XmlNode child = 5;
+}
+
+// A namespace declaration on an XmlElement (xmlns:android="http://...").
+message XmlNamespace {
+  optional string prefix = 1;
+  optional string uri = 2;
+
+  // Source line and column info.
+  optional SourcePosition source = 3;
+}
+
+// An attribute defined on an XmlElement (android:text="...").
+message XmlAttribute {
+  optional string namespace_uri = 1;
+  optional string name = 2;
+  optional string value = 3;
+
+  // Source line and column info.
+  optional SourcePosition source = 4;
+
+  // The resource ID (0xPPTTEEEE) of the attribute.
+  optional uint32 resource_id = 5;
+
+  // The interpreted/compiled version of the `value` string.
+  optional Item compiled_item = 6;
+}
diff --git a/tools/aapt2/ResourcesInternal.proto b/tools/aapt2/ResourcesInternal.proto
new file mode 100644
index 0000000..3117917
--- /dev/null
+++ b/tools/aapt2/ResourcesInternal.proto
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+syntax = "proto2";
+
+option java_package = "android.aapt.pb.internal";
+option optimize_for = LITE_RUNTIME;
+
+import "frameworks/base/tools/aapt2/Resources.proto";
+
+package aapt.pb.internal;
+
+// The top level message representing an external resource file (layout XML, PNG, etc).
+// This is used to represent a compiled file before it is linked. Only useful to aapt2.
+message CompiledFile {
+  message Symbol {
+    // The name of the symbol (in the form package:type/name).
+    optional string resource_name = 1;
+
+    // The position in the file at which this symbol is defined. For debug use.
+    optional aapt.pb.SourcePosition source = 2;
+  }
+
+  // The name of the resource (in the form package:type/name).
+  optional string resource_name = 1;
+
+  // The configuration for which the resource is defined.
+  optional aapt.pb.ConfigDescription config = 2;
+
+  // The filesystem path to where the source file originated.
+  // Mainly used to display helpful error messages.
+  optional string source_path = 3;
+
+  // Any symbols this file auto-generates/exports (eg. @+id/foo in an XML file).
+  repeated Symbol exported_symbol = 4;
+
+  // If this is a compiled XML file, this is the root node.
+  optional aapt.pb.XmlNode xml_root = 5;
+}
diff --git a/tools/aapt2/ValueVisitor.h b/tools/aapt2/ValueVisitor.h
index 2763d49..eb4fa49 100644
--- a/tools/aapt2/ValueVisitor.h
+++ b/tools/aapt2/ValueVisitor.h
@@ -80,7 +80,7 @@
   }
 
   void VisitSubValues(Array* array) {
-    for (std::unique_ptr<Item>& item : array->items) {
+    for (std::unique_ptr<Item>& item : array->elements) {
       item->Accept(this);
     }
   }
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index b64cd8c..7f5bbf0 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -16,11 +16,11 @@
 
 #include <dirent.h>
 
-#include <fstream>
 #include <string>
 
 #include "android-base/errors.h"
 #include "android-base/file.h"
+#include "android-base/utf8.h"
 #include "androidfw/StringPiece.h"
 #include "google/protobuf/io/coded_stream.h"
 #include "google/protobuf/io/zero_copy_stream_impl_lite.h"
@@ -38,6 +38,7 @@
 #include "flatten/Archive.h"
 #include "flatten/XmlFlattener.h"
 #include "io/BigBufferOutputStream.h"
+#include "io/FileInputStream.h"
 #include "io/Util.h"
 #include "proto/ProtoSerialize.h"
 #include "util/Files.h"
@@ -46,8 +47,9 @@
 #include "xml/XmlDom.h"
 #include "xml/XmlPullParser.h"
 
-using android::StringPiece;
-using google::protobuf::io::CopyingOutputStreamAdaptor;
+using ::aapt::io::FileInputStream;
+using ::android::StringPiece;
+using ::google::protobuf::io::CopyingOutputStreamAdaptor;
 
 namespace aapt {
 
@@ -57,19 +59,14 @@
   std::string name;
   std::string extension;
 
-  // Original config str. We keep this because when we parse the config, we may
-  // add on
-  // version qualifiers. We want to preserve the original input so the output is
-  // easily
+  // Original config str. We keep this because when we parse the config, we may add on
+  // version qualifiers. We want to preserve the original input so the output is easily
   // computed before hand.
   std::string config_str;
   ConfigDescription config;
 };
 
-/**
- * Resource file paths are expected to look like:
- * [--/res/]type[-config]/name
- */
+// Resource file paths are expected to look like: [--/res/]type[-config]/name
 static Maybe<ResourcePathData> ExtractResourcePathData(const std::string& path,
                                                        std::string* out_error) {
   std::vector<std::string> parts = util::Split(path, file::sDirSep);
@@ -137,9 +134,7 @@
   return util::StartsWith(filename, ".");
 }
 
-/**
- * Walks the res directory structure, looking for resource files.
- */
+// Walks the res directory structure, looking for resource files.
 static bool LoadInputFilesFromDir(IAaptContext* context, const CompileOptions& options,
                                   std::vector<ResourcePathData>* out_path_data) {
   const std::string& root_dir = options.res_dir.value();
@@ -195,22 +190,20 @@
                          const std::string& output_path) {
   ResourceTable table;
   {
-    std::ifstream fin(path_data.source.path, std::ifstream::binary);
-    if (!fin) {
+    FileInputStream fin(path_data.source.path);
+    if (fin.HadError()) {
       context->GetDiagnostics()->Error(DiagMessage(path_data.source)
-                                       << "failed to open file: "
-                                       << android::base::SystemErrorCodeToString(errno));
+                                       << "failed to open file: " << fin.GetError());
       return false;
     }
 
     // Parse the values file from XML.
-    xml::XmlPullParser xml_parser(fin);
+    xml::XmlPullParser xml_parser(&fin);
 
     ResourceParserOptions parser_options;
     parser_options.error_on_positional_arguments = !options.legacy_mode;
 
-    // If the filename includes donottranslate, then the default translatable is
-    // false.
+    // If the filename includes donottranslate, then the default translatable is false.
     parser_options.translatable = path_data.name.find("donottranslate") == std::string::npos;
 
     ResourceParser res_parser(context->GetDiagnostics(), &table, path_data.source, path_data.config,
@@ -218,8 +211,6 @@
     if (!res_parser.Parse(&xml_parser)) {
       return false;
     }
-
-    fin.close();
   }
 
   if (options.pseudolocalize) {
@@ -239,8 +230,7 @@
   // Assign an ID to any package that has resources.
   for (auto& pkg : table.packages) {
     if (!pkg->id) {
-      // If no package ID was set while parsing (public identifiers), auto
-      // assign an ID.
+      // If no package ID was set while parsing (public identifiers), auto assign an ID.
       pkg->id = context->GetPackageId();
     }
   }
@@ -292,7 +282,7 @@
     // Number of CompiledFiles.
     output_stream.WriteLittleEndian32(1);
 
-    std::unique_ptr<pb::CompiledFile> compiled_file = SerializeCompiledFileToPb(file);
+    std::unique_ptr<pb::internal::CompiledFile> compiled_file = SerializeCompiledFileToPb(file);
     output_stream.WriteCompiledFile(compiled_file.get());
     output_stream.WriteData(&buffer);
 
@@ -329,7 +319,7 @@
     // Number of CompiledFiles.
     output_stream.WriteLittleEndian32(1);
 
-    std::unique_ptr<pb::CompiledFile> compiled_file = SerializeCompiledFileToPb(file);
+    std::unique_ptr<pb::internal::CompiledFile> compiled_file = SerializeCompiledFileToPb(file);
     output_stream.WriteCompiledFile(compiled_file.get());
     output_stream.WriteData(map.getDataPtr(), map.getDataLength());
 
@@ -356,7 +346,8 @@
     return false;
   }
 
-  std::unique_ptr<pb::CompiledFile> pb_compiled_file = SerializeCompiledFileToPb(xmlres->file);
+  std::unique_ptr<pb::internal::CompiledFile> pb_compiled_file =
+      SerializeCompiledFileToPb(xmlres->file);
   out->WriteCompiledFile(pb_compiled_file.get());
   out->WriteData(&buffer);
 
@@ -367,7 +358,7 @@
   return true;
 }
 
-static bool IsValidFile(IAaptContext* context, const StringPiece& input_path) {
+static bool IsValidFile(IAaptContext* context, const std::string& input_path) {
   const file::FileType file_type = file::GetFileType(input_path);
   if (file_type != file::FileType::kRegular && file_type != file::FileType::kSymlink) {
     if (file_type == file::FileType::kDirectory) {
@@ -393,17 +384,14 @@
 
   std::unique_ptr<xml::XmlResource> xmlres;
   {
-    std::ifstream fin(path_data.source.path, std::ifstream::binary);
-    if (!fin) {
+    FileInputStream fin(path_data.source.path);
+    if (fin.HadError()) {
       context->GetDiagnostics()->Error(DiagMessage(path_data.source)
-                                       << "failed to open file: "
-                                       << android::base::SystemErrorCodeToString(errno));
+                                       << "failed to open file: " << fin.GetError());
       return false;
     }
 
     xmlres = xml::Inflate(&fin, context->GetDiagnostics(), path_data.source);
-
-    fin.close();
   }
 
   if (!xmlres) {
@@ -432,12 +420,9 @@
     return false;
   }
 
-  // Make sure CopyingOutputStreamAdaptor is deleted before we call
-  // writer->FinishEntry().
+  // Make sure CopyingOutputStreamAdaptor is deleted before we call writer->FinishEntry().
   {
-    // Wrap our IArchiveWriter with an adaptor that implements the
-    // ZeroCopyOutputStream
-    // interface.
+    // Wrap our IArchiveWriter with an adaptor that implements the ZeroCopyOutputStream interface.
     CopyingOutputStreamAdaptor copying_adaptor(writer);
     CompiledFileOutputStream output_stream(&copying_adaptor);
 
diff --git a/tools/aapt2/cmd/Dump.cpp b/tools/aapt2/cmd/Dump.cpp
index aa94723..0965910 100644
--- a/tools/aapt2/cmd/Dump.cpp
+++ b/tools/aapt2/cmd/Dump.cpp
@@ -27,11 +27,11 @@
 #include "unflatten/BinaryResourceParser.h"
 #include "util/Files.h"
 
-using android::StringPiece;
+using ::android::StringPiece;
 
 namespace aapt {
 
-bool DumpCompiledFile(const pb::CompiledFile& pb_file, const void* data, size_t len,
+bool DumpCompiledFile(const pb::internal::CompiledFile& pb_file, const void* data, size_t len,
                       const Source& source, IAaptContext* context) {
   std::unique_ptr<ResourceFile> file =
       DeserializeCompiledFileFromPb(pb_file, source, context->GetDiagnostics());
@@ -118,7 +118,7 @@
       }
 
       for (uint32_t i = 0; i < num_files; i++) {
-        pb::CompiledFile compiled_file;
+        pb::internal::CompiledFile compiled_file;
         if (!input.ReadCompiledFile(&compiled_file)) {
           context->GetDiagnostics()->Warn(DiagMessage() << "failed to read compiled file");
           return false;
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 5ad0cdd..d9e7ac6 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -40,6 +40,7 @@
 #include "flatten/TableFlattener.h"
 #include "flatten/XmlFlattener.h"
 #include "io/BigBufferInputStream.h"
+#include "io/FileInputStream.h"
 #include "io/FileSystem.h"
 #include "io/Util.h"
 #include "io/ZipArchive.h"
@@ -61,8 +62,9 @@
 #include "util/Files.h"
 #include "xml/XmlDom.h"
 
-using android::StringPiece;
-using android::base::StringPrintf;
+using ::aapt::io::FileInputStream;
+using ::android::StringPiece;
+using ::android::base::StringPrintf;
 
 namespace aapt {
 
@@ -284,13 +286,11 @@
   return table;
 }
 
-/**
- * Inflates an XML file from the source path.
- */
+// Inflates an XML file from the source path.
 static std::unique_ptr<xml::XmlResource> LoadXml(const std::string& path, IDiagnostics* diag) {
-  std::ifstream fin(path, std::ifstream::binary);
-  if (!fin) {
-    diag->Error(DiagMessage(path) << strerror(errno));
+  FileInputStream fin(path);
+  if (fin.HadError()) {
+    diag->Error(DiagMessage(path) << "failed to load XML file: " << fin.GetError());
     return {};
   }
   return xml::Inflate(&fin, diag, Source(path));
@@ -482,7 +482,7 @@
 
   if (options_.no_version_vectors || options_.no_version_transitions) {
     // Skip this if it is a vector or animated-vector.
-    xml::Element* el = xml::FindRootElement(doc);
+    xml::Element* el = doc->root.get();
     if (el && el->namespace_uri.empty()) {
       if ((options_.no_version_vectors && IsVectorElement(el->name)) ||
           (options_.no_version_transitions && IsTransitionElement(el->name))) {
@@ -1295,7 +1295,7 @@
       }
 
       for (uint32_t i = 0; i < num_files; i++) {
-        pb::CompiledFile compiled_file;
+        pb::internal::CompiledFile compiled_file;
         if (!input_stream.ReadCompiledFile(&compiled_file)) {
           context_->GetDiagnostics()->Error(DiagMessage(src)
                                             << "failed to read compiled file header");
diff --git a/tools/aapt2/cmd/Util.cpp b/tools/aapt2/cmd/Util.cpp
index e1c45d6..d17858d 100644
--- a/tools/aapt2/cmd/Util.cpp
+++ b/tools/aapt2/cmd/Util.cpp
@@ -28,7 +28,7 @@
 #include "util/Maybe.h"
 #include "util/Util.h"
 
-using android::StringPiece;
+using ::android::StringPiece;
 
 namespace aapt {
 
@@ -134,19 +134,21 @@
   return xml::AaptAttribute(Attribute(), id);
 }
 
+static xml::NamespaceDecl CreateAndroidNamespaceDecl() {
+  xml::NamespaceDecl decl;
+  decl.prefix = "android";
+  decl.uri = xml::kSchemaAndroid;
+  return decl;
+}
+
 std::unique_ptr<xml::XmlResource> GenerateSplitManifest(const AppInfo& app_info,
                                                         const SplitConstraints& constraints) {
   const ResourceId kVersionCode(0x0101021b);
   const ResourceId kRevisionCode(0x010104d5);
   const ResourceId kHasCode(0x0101000c);
 
-  std::unique_ptr<xml::XmlResource> doc = util::make_unique<xml::XmlResource>();
-
-  std::unique_ptr<xml::Namespace> namespace_android = util::make_unique<xml::Namespace>();
-  namespace_android->namespace_uri = xml::kSchemaAndroid;
-  namespace_android->namespace_prefix = "android";
-
   std::unique_ptr<xml::Element> manifest_el = util::make_unique<xml::Element>();
+  manifest_el->namespace_decls.push_back(CreateAndroidNamespaceDecl());
   manifest_el->name = "manifest";
   manifest_el->attributes.push_back(xml::Attribute{"", "package", app_info.package});
 
@@ -179,8 +181,8 @@
         xml::Attribute{"", "configForSplit", app_info.split_name.value()});
   }
 
-  // Splits may contain more configurations than originally desired (fallback densities, etc.).
-  // This makes programmatic discovery of split targetting difficult. Encode the original
+  // Splits may contain more configurations than originally desired (fall-back densities, etc.).
+  // This makes programmatic discovery of split targeting difficult. Encode the original
   // split constraints intended for this split.
   std::stringstream target_config_str;
   target_config_str << util::Joiner(constraints.configs, ",");
@@ -193,8 +195,9 @@
                      util::make_unique<BinaryPrimitive>(android::Res_value::TYPE_INT_BOOLEAN, 0u)});
 
   manifest_el->AppendChild(std::move(application_el));
-  namespace_android->AppendChild(std::move(manifest_el));
-  doc->root = std::move(namespace_android);
+
+  std::unique_ptr<xml::XmlResource> doc = util::make_unique<xml::XmlResource>();
+  doc->root = std::move(manifest_el);
   return doc;
 }
 
@@ -284,7 +287,7 @@
 
 Maybe<AppInfo> ExtractAppInfoFromBinaryManifest(xml::XmlResource* xml_res, IDiagnostics* diag) {
   // Make sure the first element is <manifest> with package attribute.
-  xml::Element* manifest_el = xml::FindRootElement(xml_res->root.get());
+  xml::Element* manifest_el = xml_res->root.get();
   if (manifest_el == nullptr) {
     return {};
   }
diff --git a/tools/aapt2/compile/InlineXmlFormatParser.cpp b/tools/aapt2/compile/InlineXmlFormatParser.cpp
index 786494b..857cdd5 100644
--- a/tools/aapt2/compile/InlineXmlFormatParser.cpp
+++ b/tools/aapt2/compile/InlineXmlFormatParser.cpp
@@ -16,12 +16,8 @@
 
 #include "compile/InlineXmlFormatParser.h"
 
-#include <sstream>
 #include <string>
 
-#include "android-base/macros.h"
-
-#include "Debug.h"
 #include "ResourceUtils.h"
 #include "util/Util.h"
 #include "xml/XmlDom.h"
@@ -31,19 +27,17 @@
 
 namespace {
 
-/**
- * XML Visitor that will find all <aapt:attr> elements for extraction.
- */
+struct InlineDeclaration {
+  xml::Element* el;
+  std::string attr_namespace_uri;
+  std::string attr_name;
+};
+
+// XML Visitor that will find all <aapt:attr> elements for extraction.
 class Visitor : public xml::PackageAwareVisitor {
  public:
   using xml::PackageAwareVisitor::Visit;
 
-  struct InlineDeclaration {
-    xml::Element* el;
-    std::string attr_namespace_uri;
-    std::string attr_name;
-  };
-
   explicit Visitor(IAaptContext* context, xml::XmlResource* xml_resource)
       : context_(context), xml_resource_(xml_resource) {}
 
@@ -53,51 +47,44 @@
       return;
     }
 
-    const Source& src = xml_resource_->file.source.WithLine(el->line_number);
+    const Source src = xml_resource_->file.source.WithLine(el->line_number);
 
     xml::Attribute* attr = el->FindAttribute({}, "name");
     if (!attr) {
-      context_->GetDiagnostics()->Error(DiagMessage(src)
-                                        << "missing 'name' attribute");
+      context_->GetDiagnostics()->Error(DiagMessage(src) << "missing 'name' attribute");
       error_ = true;
       return;
     }
 
     Maybe<Reference> ref = ResourceUtils::ParseXmlAttributeName(attr->value);
     if (!ref) {
-      context_->GetDiagnostics()->Error(
-          DiagMessage(src) << "invalid XML attribute '" << attr->value << "'");
+      context_->GetDiagnostics()->Error(DiagMessage(src) << "invalid XML attribute '" << attr->value
+                                                         << "'");
       error_ = true;
       return;
     }
 
     const ResourceName& name = ref.value().name.value();
 
-    // Use an empty string for the compilation package because we don't want to
-    // default to
-    // the local package if the user specified name="style" or something. This
-    // should just
+    // Use an empty string for the compilation package because we don't want to default to
+    // the local package if the user specified name="style" or something. This should just
     // be the default namespace.
-    Maybe<xml::ExtractedPackage> maybe_pkg =
-        TransformPackageAlias(name.package, {});
+    Maybe<xml::ExtractedPackage> maybe_pkg = TransformPackageAlias(name.package, {});
     if (!maybe_pkg) {
-      context_->GetDiagnostics()->Error(DiagMessage(src)
-                                        << "invalid namespace prefix '"
-                                        << name.package << "'");
+      context_->GetDiagnostics()->Error(DiagMessage(src) << "invalid namespace prefix '"
+                                                         << name.package << "'");
       error_ = true;
       return;
     }
 
     const xml::ExtractedPackage& pkg = maybe_pkg.value();
-    const bool private_namespace =
-        pkg.private_namespace || ref.value().private_reference;
+    const bool private_namespace = pkg.private_namespace || ref.value().private_reference;
 
     InlineDeclaration decl;
     decl.el = el;
     decl.attr_name = name.entry;
     if (!pkg.package.empty()) {
-      decl.attr_namespace_uri =
-          xml::BuildPackageNamespace(pkg.package, private_namespace);
+      decl.attr_namespace_uri = xml::BuildPackageNamespace(pkg.package, private_namespace);
     }
 
     inline_declarations_.push_back(std::move(decl));
@@ -107,7 +94,9 @@
     return inline_declarations_;
   }
 
-  bool HasError() const { return error_; }
+  bool HasError() const {
+    return error_;
+  }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(Visitor);
@@ -120,8 +109,7 @@
 
 }  // namespace
 
-bool InlineXmlFormatParser::Consume(IAaptContext* context,
-                                    xml::XmlResource* doc) {
+bool InlineXmlFormatParser::Consume(IAaptContext* context, xml::XmlResource* doc) {
   Visitor visitor(context, doc);
   doc->root->Accept(&visitor);
   if (visitor.HasError()) {
@@ -129,69 +117,53 @@
   }
 
   size_t name_suffix_counter = 0;
-  for (const Visitor::InlineDeclaration& decl :
-       visitor.GetInlineDeclarations()) {
+  for (const InlineDeclaration& decl : visitor.GetInlineDeclarations()) {
     auto new_doc = util::make_unique<xml::XmlResource>();
     new_doc->file.config = doc->file.config;
     new_doc->file.source = doc->file.source.WithLine(decl.el->line_number);
     new_doc->file.name = doc->file.name;
 
     // Modify the new entry name. We need to suffix the entry with a number to
-    // avoid
-    // local collisions, then mangle it with the empty package, such that it
-    // won't show up
+    // avoid local collisions, then mangle it with the empty package, such that it won't show up
     // in R.java.
-
-    new_doc->file.name.entry =
-        NameMangler::MangleEntry({}, new_doc->file.name.entry + "__" +
-                                         std::to_string(name_suffix_counter));
+    new_doc->file.name.entry = NameMangler::MangleEntry(
+        {}, new_doc->file.name.entry + "__" + std::to_string(name_suffix_counter));
 
     // Extracted elements must be the only child of <aapt:attr>.
     // Make sure there is one root node in the children (ignore empty text).
-    for (auto& child : decl.el->children) {
+    for (std::unique_ptr<xml::Node>& child : decl.el->children) {
       const Source child_source = doc->file.source.WithLine(child->line_number);
       if (xml::Text* t = xml::NodeCast<xml::Text>(child.get())) {
         if (!util::TrimWhitespace(t->text).empty()) {
-          context->GetDiagnostics()->Error(
-              DiagMessage(child_source)
-              << "can't extract text into its own resource");
+          context->GetDiagnostics()->Error(DiagMessage(child_source)
+                                           << "can't extract text into its own resource");
           return false;
         }
       } else if (new_doc->root) {
-        context->GetDiagnostics()->Error(
-            DiagMessage(child_source)
-            << "inline XML resources must have a single root");
+        context->GetDiagnostics()->Error(DiagMessage(child_source)
+                                         << "inline XML resources must have a single root");
         return false;
       } else {
-        new_doc->root = std::move(child);
+        new_doc->root.reset(static_cast<xml::Element*>(child.release()));
         new_doc->root->parent = nullptr;
       }
     }
 
-    // Walk up and find the parent element.
-    xml::Node* node = decl.el;
-    xml::Element* parent_el = nullptr;
-    while (node->parent &&
-           (parent_el = xml::NodeCast<xml::Element>(node->parent)) == nullptr) {
-      node = node->parent;
-    }
-
+    // Get the parent element of <aapt:attr>
+    xml::Element* parent_el = decl.el->parent;
     if (!parent_el) {
-      context->GetDiagnostics()->Error(
-          DiagMessage(new_doc->file.source)
-          << "no suitable parent for inheriting attribute");
+      context->GetDiagnostics()->Error(DiagMessage(new_doc->file.source)
+                                       << "no suitable parent for inheriting attribute");
       return false;
     }
 
     // Add the inline attribute to the parent.
-    parent_el->attributes.push_back(
-        xml::Attribute{decl.attr_namespace_uri, decl.attr_name,
-                       "@" + new_doc->file.name.ToString()});
+    parent_el->attributes.push_back(xml::Attribute{decl.attr_namespace_uri, decl.attr_name,
+                                                   "@" + new_doc->file.name.ToString()});
 
     // Delete the subtree.
-    for (auto iter = parent_el->children.begin();
-         iter != parent_el->children.end(); ++iter) {
-      if (iter->get() == node) {
+    for (auto iter = parent_el->children.begin(); iter != parent_el->children.end(); ++iter) {
+      if (iter->get() == decl.el) {
         parent_el->children.erase(iter);
         break;
       }
diff --git a/tools/aapt2/compile/InlineXmlFormatParser.h b/tools/aapt2/compile/InlineXmlFormatParser.h
index 1a658fd..4300023 100644
--- a/tools/aapt2/compile/InlineXmlFormatParser.h
+++ b/tools/aapt2/compile/InlineXmlFormatParser.h
@@ -26,35 +26,30 @@
 
 namespace aapt {
 
-/**
- * Extracts Inline XML definitions into their own xml::XmlResource objects.
- *
- * Inline XML looks like:
- *
- * <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
- *                  xmlns:aapt="http://schemas.android.com/aapt" >
- *   <aapt:attr name="android:drawable" >
- *     <vector
- *       android:height="64dp"
- *       android:width="64dp"
- *       android:viewportHeight="600"
- *       android:viewportWidth="600"/>
- *   </aapt:attr>
- * </animated-vector>
- *
- * The <vector> will be extracted into its own XML file and <animated-vector>
- * will
- * gain an attribute 'android:drawable' set to a reference to the extracted
- * <vector> resource.
- */
+// Extracts Inline XML definitions into their own xml::XmlResource objects.
+//
+// Inline XML looks like:
+//
+// <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+//                  xmlns:aapt="http://schemas.android.com/aapt" >
+//   <aapt:attr name="android:drawable" >
+//     <vector
+//       android:height="64dp"
+//       android:width="64dp"
+//       android:viewportHeight="600"
+//       android:viewportWidth="600"/>
+//   </aapt:attr>
+// </animated-vector>
+//
+// The <vector> will be extracted into its own XML file and <animated-vector> will
+// gain an attribute 'android:drawable' set to a reference to the extracted <vector> resource.
 class InlineXmlFormatParser : public IXmlResourceConsumer {
  public:
   explicit InlineXmlFormatParser() = default;
 
   bool Consume(IAaptContext* context, xml::XmlResource* doc) override;
 
-  std::vector<std::unique_ptr<xml::XmlResource>>&
-  GetExtractedInlineXmlDocuments() {
+  std::vector<std::unique_ptr<xml::XmlResource>>& GetExtractedInlineXmlDocuments() {
     return queue_;
   }
 
diff --git a/tools/aapt2/compile/InlineXmlFormatParser_test.cpp b/tools/aapt2/compile/InlineXmlFormatParser_test.cpp
index 348796c..de7739a 100644
--- a/tools/aapt2/compile/InlineXmlFormatParser_test.cpp
+++ b/tools/aapt2/compile/InlineXmlFormatParser_test.cpp
@@ -18,25 +18,32 @@
 
 #include "test/Test.h"
 
+using ::testing::Eq;
+using ::testing::IsNull;
+using ::testing::Not;
+using ::testing::NotNull;
+using ::testing::SizeIs;
+using ::testing::StrEq;
+
 namespace aapt {
 
 TEST(InlineXmlFormatParserTest, PassThrough) {
   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
-  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"EOF(
+  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(
       <View xmlns:android="http://schemas.android.com/apk/res/android">
         <View android:text="hey">
           <View android:id="hi" />
         </View>
-      </View>)EOF");
+      </View>)");
 
   InlineXmlFormatParser parser;
   ASSERT_TRUE(parser.Consume(context.get(), doc.get()));
-  EXPECT_EQ(0u, parser.GetExtractedInlineXmlDocuments().size());
+  EXPECT_THAT(parser.GetExtractedInlineXmlDocuments(), SizeIs(0u));
 }
 
 TEST(InlineXmlFormatParserTest, ExtractOneXmlResource) {
   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
-  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"EOF(
+  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(
       <View1 xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:aapt="http://schemas.android.com/aapt">
         <aapt:attr name="android:text">
@@ -44,7 +51,7 @@
             <View3 android:id="hi" />
           </View2>
         </aapt:attr>
-      </View1>)EOF");
+      </View1>)");
 
   doc->file.name = test::ParseNameOrDie("layout/main");
 
@@ -52,42 +59,38 @@
   ASSERT_TRUE(parser.Consume(context.get(), doc.get()));
 
   // One XML resource should have been extracted.
-  EXPECT_EQ(1u, parser.GetExtractedInlineXmlDocuments().size());
+  EXPECT_THAT(parser.GetExtractedInlineXmlDocuments(), SizeIs(1u));
 
-  xml::Element* el = xml::FindRootElement(doc.get());
-  ASSERT_NE(nullptr, el);
-
-  EXPECT_EQ("View1", el->name);
+  xml::Element* el = doc->root.get();
+  ASSERT_THAT(el, NotNull());
+  EXPECT_THAT(el->name, StrEq("View1"));
 
   // The <aapt:attr> tag should be extracted.
-  EXPECT_EQ(nullptr, el->FindChild(xml::kSchemaAapt, "attr"));
+  EXPECT_THAT(el->FindChild(xml::kSchemaAapt, "attr"), IsNull());
 
   // The 'android:text' attribute should be set with a reference.
   xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "text");
-  ASSERT_NE(nullptr, attr);
+  ASSERT_THAT(attr, NotNull());
 
   ResourceNameRef name_ref;
   ASSERT_TRUE(ResourceUtils::ParseReference(attr->value, &name_ref));
 
-  xml::XmlResource* extracted_doc =
-      parser.GetExtractedInlineXmlDocuments()[0].get();
-  ASSERT_NE(nullptr, extracted_doc);
+  xml::XmlResource* extracted_doc = parser.GetExtractedInlineXmlDocuments()[0].get();
+  ASSERT_THAT(extracted_doc, NotNull());
 
   // Make sure the generated reference is correct.
-  EXPECT_EQ(name_ref.package, extracted_doc->file.name.package);
-  EXPECT_EQ(name_ref.type, extracted_doc->file.name.type);
-  EXPECT_EQ(name_ref.entry, extracted_doc->file.name.entry);
+  EXPECT_THAT(extracted_doc->file.name, Eq(name_ref));
 
   // Verify the structure of the extracted XML.
-  el = xml::FindRootElement(extracted_doc);
-  ASSERT_NE(nullptr, el);
-  EXPECT_EQ("View2", el->name);
-  EXPECT_NE(nullptr, el->FindChild({}, "View3"));
+  el = extracted_doc->root.get();
+  ASSERT_THAT(el, NotNull());
+  EXPECT_THAT(el->name, StrEq("View2"));
+  EXPECT_THAT(el->FindChild({}, "View3"), NotNull());
 }
 
 TEST(InlineXmlFormatParserTest, ExtractTwoXmlResources) {
   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
-  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"EOF(
+  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(
       <View1 xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:aapt="http://schemas.android.com/aapt">
         <aapt:attr name="android:text">
@@ -99,45 +102,39 @@
         <aapt:attr name="android:drawable">
           <vector />
         </aapt:attr>
-      </View1>)EOF");
+      </View1>)");
 
   doc->file.name = test::ParseNameOrDie("layout/main");
 
   InlineXmlFormatParser parser;
   ASSERT_TRUE(parser.Consume(context.get(), doc.get()));
-  ASSERT_EQ(2u, parser.GetExtractedInlineXmlDocuments().size());
+  ASSERT_THAT(parser.GetExtractedInlineXmlDocuments(), SizeIs(2u));
 
-  xml::Element* el = xml::FindRootElement(doc.get());
-  ASSERT_NE(nullptr, el);
-
-  EXPECT_EQ("View1", el->name);
+  xml::Element* el = doc->root.get();
+  ASSERT_THAT(el, NotNull());
+  EXPECT_THAT(el->name, StrEq("View1"));
 
   xml::Attribute* attr_text = el->FindAttribute(xml::kSchemaAndroid, "text");
-  ASSERT_NE(nullptr, attr_text);
+  ASSERT_THAT(attr_text, NotNull());
 
-  xml::Attribute* attr_drawable =
-      el->FindAttribute(xml::kSchemaAndroid, "drawable");
-  ASSERT_NE(nullptr, attr_drawable);
+  xml::Attribute* attr_drawable = el->FindAttribute(xml::kSchemaAndroid, "drawable");
+  ASSERT_THAT(attr_drawable, NotNull());
 
   // The two extracted resources should have different names.
-  EXPECT_NE(attr_text->value, attr_drawable->value);
+  EXPECT_THAT(attr_text->value, Not(Eq(attr_drawable->value)));
 
   // The child <aapt:attr> elements should be gone.
-  EXPECT_EQ(nullptr, el->FindChild(xml::kSchemaAapt, "attr"));
+  EXPECT_THAT(el->FindChild(xml::kSchemaAapt, "attr"), IsNull());
 
-  xml::XmlResource* extracted_doc_text =
-      parser.GetExtractedInlineXmlDocuments()[0].get();
-  ASSERT_NE(nullptr, extracted_doc_text);
-  el = xml::FindRootElement(extracted_doc_text);
-  ASSERT_NE(nullptr, el);
-  EXPECT_EQ("View2", el->name);
+  xml::XmlResource* extracted_doc_text = parser.GetExtractedInlineXmlDocuments()[0].get();
+  ASSERT_THAT(extracted_doc_text, NotNull());
+  ASSERT_THAT(extracted_doc_text->root, NotNull());
+  EXPECT_THAT(extracted_doc_text->root->name, StrEq("View2"));
 
-  xml::XmlResource* extracted_doc_drawable =
-      parser.GetExtractedInlineXmlDocuments()[1].get();
-  ASSERT_NE(nullptr, extracted_doc_drawable);
-  el = xml::FindRootElement(extracted_doc_drawable);
-  ASSERT_NE(nullptr, el);
-  EXPECT_EQ("vector", el->name);
+  xml::XmlResource* extracted_doc_drawable = parser.GetExtractedInlineXmlDocuments()[1].get();
+  ASSERT_THAT(extracted_doc_drawable, NotNull());
+  ASSERT_THAT(extracted_doc_drawable->root, NotNull());
+  EXPECT_THAT(extracted_doc_drawable->root->name, StrEq("vector"));
 }
 
 }  // namespace aapt
diff --git a/tools/aapt2/configuration/ConfigurationParser.cpp b/tools/aapt2/configuration/ConfigurationParser.cpp
index d051120..bdccf8b 100644
--- a/tools/aapt2/configuration/ConfigurationParser.cpp
+++ b/tools/aapt2/configuration/ConfigurationParser.cpp
@@ -22,13 +22,14 @@
 #include <memory>
 #include <utility>
 
-#include <android-base/file.h>
-#include <android-base/logging.h>
+#include "android-base/file.h"
+#include "android-base/logging.h"
 
 #include "ConfigDescription.h"
 #include "Diagnostics.h"
 #include "io/File.h"
 #include "io/FileSystem.h"
+#include "io/StringInputStream.h"
 #include "util/Maybe.h"
 #include "util/Util.h"
 #include "xml/XmlActionExecutor.h"
@@ -49,9 +50,9 @@
 using ::aapt::configuration::Locale;
 using ::aapt::io::IFile;
 using ::aapt::io::RegularFile;
+using ::aapt::io::StringInputStream;
 using ::aapt::util::TrimWhitespace;
 using ::aapt::xml::Element;
-using ::aapt::xml::FindRootElement;
 using ::aapt::xml::NodeCast;
 using ::aapt::xml::XmlActionExecutor;
 using ::aapt::xml::XmlActionExecutorPolicy;
@@ -182,15 +183,14 @@
 }
 
 Maybe<PostProcessingConfiguration> ConfigurationParser::Parse() {
-  std::istringstream in(contents_);
-
-  auto doc = xml::Inflate(&in, diag_, Source("config.xml"));
+  StringInputStream in(contents_);
+  std::unique_ptr<xml::XmlResource> doc = xml::Inflate(&in, diag_, Source("config.xml"));
   if (!doc) {
     return {};
   }
 
   // Strip any namespaces from the XML as the XmlActionExecutor ignores anything with a namespace.
-  auto* root = FindRootElement(doc.get());
+  Element* root = doc->root.get();
   if (root == nullptr) {
     diag_->Error(DiagMessage() << "Could not find the root element in the XML document");
     return {};
diff --git a/tools/aapt2/configuration/ConfigurationParser_test.cpp b/tools/aapt2/configuration/ConfigurationParser_test.cpp
index fb71e98..f897737 100644
--- a/tools/aapt2/configuration/ConfigurationParser_test.cpp
+++ b/tools/aapt2/configuration/ConfigurationParser_test.cpp
@@ -18,9 +18,6 @@
 
 #include <string>
 
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
 #include "androidfw/ResourceTypes.h"
 
 #include "test/Test.h"
@@ -29,7 +26,7 @@
 namespace aapt {
 namespace {
 
-using android::ResTable_config;
+using ::android::ResTable_config;
 using configuration::Abi;
 using configuration::AndroidSdk;
 using configuration::Artifact;
@@ -38,7 +35,7 @@
 using configuration::GlTexture;
 using configuration::Locale;
 using configuration::AndroidManifest;
-using testing::ElementsAre;
+using ::testing::ElementsAre;
 using xml::Element;
 using xml::NodeCast;
 
@@ -192,7 +189,7 @@
   auto doc = test::BuildXmlDom(xml);
 
   PostProcessingConfiguration config;
-  bool ok = artifact_handler_(&config, NodeCast<Element>(doc.get()->root.get()), &diag_);
+  bool ok = artifact_handler_(&config, NodeCast<Element>(doc->root.get()), &diag_);
   ASSERT_TRUE(ok);
 
   EXPECT_EQ(1ul, config.artifacts.size());
diff --git a/tools/aapt2/flatten/Archive.cpp b/tools/aapt2/flatten/Archive.cpp
index 826f91b..5f8bd06 100644
--- a/tools/aapt2/flatten/Archive.cpp
+++ b/tools/aapt2/flatten/Archive.cpp
@@ -23,12 +23,14 @@
 
 #include "android-base/errors.h"
 #include "android-base/macros.h"
+#include "android-base/utf8.h"
 #include "androidfw/StringPiece.h"
 #include "ziparchive/zip_writer.h"
 
 #include "util/Files.h"
 
-using android::StringPiece;
+using ::android::StringPiece;
+using ::android::base::SystemErrorCodeToString;
 
 namespace aapt {
 
@@ -58,11 +60,11 @@
 
     std::string full_path = dir_;
     file::AppendPath(&full_path, path);
-    file::mkdirs(file::GetStem(full_path));
+    file::mkdirs(file::GetStem(full_path).to_string());
 
-    file_ = {fopen(full_path.data(), "wb"), fclose};
+    file_ = {::android::base::utf8::fopen(full_path.c_str(), "wb"), fclose};
     if (!file_) {
-      error_ = android::base::SystemErrorCodeToString(errno);
+      error_ = SystemErrorCodeToString(errno);
       return false;
     }
     return true;
@@ -74,7 +76,7 @@
     }
 
     if (fwrite(data, 1, len, file_.get()) != static_cast<size_t>(len)) {
-      error_ = android::base::SystemErrorCodeToString(errno);
+      error_ = SystemErrorCodeToString(errno);
       file_.reset(nullptr);
       return false;
     }
@@ -121,9 +123,9 @@
   ZipFileWriter() = default;
 
   bool Open(const StringPiece& path) {
-    file_ = {fopen(path.data(), "w+b"), fclose};
+    file_ = {::android::base::utf8::fopen(path.to_string().c_str(), "w+b"), fclose};
     if (!file_) {
-      error_ = android::base::SystemErrorCodeToString(errno);
+      error_ = SystemErrorCodeToString(errno);
       return false;
     }
     writer_ = util::make_unique<ZipWriter>(file_.get());
diff --git a/tools/aapt2/flatten/TableFlattener.cpp b/tools/aapt2/flatten/TableFlattener.cpp
index e5993a6..14b776b 100644
--- a/tools/aapt2/flatten/TableFlattener.cpp
+++ b/tools/aapt2/flatten/TableFlattener.cpp
@@ -133,7 +133,7 @@
   }
 
   void Visit(Array* array) override {
-    for (auto& item : array->items) {
+    for (auto& item : array->elements) {
       ResTable_map* out_entry = buffer_->NextBlock<ResTable_map>();
       FlattenValue(item.get(), out_entry);
       out_entry->value.size = util::HostToDevice16(sizeof(out_entry->value));
diff --git a/tools/aapt2/flatten/XmlFlattener.cpp b/tools/aapt2/flatten/XmlFlattener.cpp
index 331ef78..b3b308a 100644
--- a/tools/aapt2/flatten/XmlFlattener.cpp
+++ b/tools/aapt2/flatten/XmlFlattener.cpp
@@ -38,12 +38,10 @@
 
 constexpr uint32_t kLowPriority = 0xffffffffu;
 
-static bool cmp_xml_attribute_by_id(const xml::Attribute* a,
-                                    const xml::Attribute* b) {
+static bool cmp_xml_attribute_by_id(const xml::Attribute* a, const xml::Attribute* b) {
   if (a->compiled_attribute && a->compiled_attribute.value().id) {
     if (b->compiled_attribute && b->compiled_attribute.value().id) {
-      return a->compiled_attribute.value().id.value() <
-             b->compiled_attribute.value().id.value();
+      return a->compiled_attribute.value().id.value() < b->compiled_attribute.value().id.value();
     }
     return true;
   } else if (!b->compiled_attribute) {
@@ -75,17 +73,6 @@
   XmlFlattenerVisitor(BigBuffer* buffer, XmlFlattenerOptions options)
       : buffer_(buffer), options_(options) {}
 
-  void Visit(xml::Namespace* node) override {
-    if (node->namespace_uri == xml::kSchemaTools) {
-      // Skip dedicated tools namespace.
-      xml::Visitor::Visit(node);
-    } else {
-      WriteNamespace(node, android::RES_XML_START_NAMESPACE_TYPE);
-      xml::Visitor::Visit(node);
-      WriteNamespace(node, android::RES_XML_END_NAMESPACE_TYPE);
-    }
-  }
-
   void Visit(xml::Text* node) override {
     if (util::TrimWhitespace(node->text).empty()) {
       // Skip whitespace only text nodes.
@@ -93,8 +80,7 @@
     }
 
     ChunkWriter writer(buffer_);
-    ResXMLTree_node* flat_node =
-        writer.StartChunk<ResXMLTree_node>(RES_XML_CDATA_TYPE);
+    ResXMLTree_node* flat_node = writer.StartChunk<ResXMLTree_node>(RES_XML_CDATA_TYPE);
     flat_node->lineNumber = util::HostToDevice32(node->line_number);
     flat_node->comment.index = util::HostToDevice32(-1);
 
@@ -109,6 +95,13 @@
   }
 
   void Visit(xml::Element* node) override {
+    for (const xml::NamespaceDecl& decl : node->namespace_decls) {
+      // Skip dedicated tools namespace.
+      if (decl.uri != xml::kSchemaTools) {
+        WriteNamespace(decl, android::RES_XML_START_NAMESPACE_TYPE);
+      }
+    }
+
     {
       ChunkWriter start_writer(buffer_);
       ResXMLTree_node* flat_node =
@@ -116,19 +109,15 @@
       flat_node->lineNumber = util::HostToDevice32(node->line_number);
       flat_node->comment.index = util::HostToDevice32(-1);
 
-      ResXMLTree_attrExt* flat_elem =
-          start_writer.NextBlock<ResXMLTree_attrExt>();
+      ResXMLTree_attrExt* flat_elem = start_writer.NextBlock<ResXMLTree_attrExt>();
 
-      // A missing namespace must be null, not an empty string. Otherwise the
-      // runtime complains.
+      // A missing namespace must be null, not an empty string. Otherwise the runtime complains.
       AddString(node->namespace_uri, kLowPriority, &flat_elem->ns,
                 true /* treat_empty_string_as_null */);
-      AddString(node->name, kLowPriority, &flat_elem->name,
-                true /* treat_empty_string_as_null */);
+      AddString(node->name, kLowPriority, &flat_elem->name, true /* treat_empty_string_as_null */);
 
       flat_elem->attributeStart = util::HostToDevice16(sizeof(*flat_elem));
-      flat_elem->attributeSize =
-          util::HostToDevice16(sizeof(ResXMLTree_attribute));
+      flat_elem->attributeSize = util::HostToDevice16(sizeof(ResXMLTree_attribute));
 
       WriteAttributes(node, flat_elem, &start_writer);
 
@@ -144,14 +133,20 @@
       flat_end_node->lineNumber = util::HostToDevice32(node->line_number);
       flat_end_node->comment.index = util::HostToDevice32(-1);
 
-      ResXMLTree_endElementExt* flat_end_elem =
-          end_writer.NextBlock<ResXMLTree_endElementExt>();
+      ResXMLTree_endElementExt* flat_end_elem = end_writer.NextBlock<ResXMLTree_endElementExt>();
       AddString(node->namespace_uri, kLowPriority, &flat_end_elem->ns,
                 true /* treat_empty_string_as_null */);
       AddString(node->name, kLowPriority, &flat_end_elem->name);
 
       end_writer.Finish();
     }
+
+    for (auto iter = node->namespace_decls.rbegin(); iter != node->namespace_decls.rend(); ++iter) {
+      // Skip dedicated tools namespace.
+      if (iter->uri != xml::kSchemaTools) {
+        WriteNamespace(*iter, android::RES_XML_END_NAMESPACE_TYPE);
+      }
+    }
   }
 
  private:
@@ -173,16 +168,16 @@
     string_refs.push_back(StringFlattenDest{ref, dest});
   }
 
-  void WriteNamespace(xml::Namespace* node, uint16_t type) {
+  void WriteNamespace(const xml::NamespaceDecl& decl, uint16_t type) {
     ChunkWriter writer(buffer_);
 
     ResXMLTree_node* flatNode = writer.StartChunk<ResXMLTree_node>(type);
-    flatNode->lineNumber = util::HostToDevice32(node->line_number);
+    flatNode->lineNumber = util::HostToDevice32(decl.line_number);
     flatNode->comment.index = util::HostToDevice32(-1);
 
     ResXMLTree_namespaceExt* flat_ns = writer.NextBlock<ResXMLTree_namespaceExt>();
-    AddString(node->namespace_prefix, kLowPriority, &flat_ns->prefix);
-    AddString(node->namespace_uri, kLowPriority, &flat_ns->uri);
+    AddString(decl.prefix, kLowPriority, &flat_ns->prefix);
+    AddString(decl.uri, kLowPriority, &flat_ns->uri);
 
     writer.Finish();
   }
diff --git a/tools/aapt2/integration-tests/AppOne/res/navigation/home.xml b/tools/aapt2/integration-tests/AppOne/res/navigation/home.xml
new file mode 100644
index 0000000..ade271d
--- /dev/null
+++ b/tools/aapt2/integration-tests/AppOne/res/navigation/home.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<navigation />
diff --git a/tools/aapt2/io/FileInputStream.cpp b/tools/aapt2/io/FileInputStream.cpp
new file mode 100644
index 0000000..07dbb5a
--- /dev/null
+++ b/tools/aapt2/io/FileInputStream.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include "io/FileInputStream.h"
+
+#include <errno.h>   // for errno
+#include <fcntl.h>   // for O_RDONLY
+#include <unistd.h>  // for read
+
+#include "android-base/errors.h"
+#include "android-base/file.h"  // for O_BINARY
+#include "android-base/macros.h"
+#include "android-base/utf8.h"
+
+using ::android::base::SystemErrorCodeToString;
+
+namespace aapt {
+namespace io {
+
+FileInputStream::FileInputStream(const std::string& path, size_t buffer_capacity)
+    : FileInputStream(::android::base::utf8::open(path.c_str(), O_RDONLY | O_BINARY),
+                      buffer_capacity) {
+}
+
+FileInputStream::FileInputStream(int fd, size_t buffer_capacity)
+    : fd_(fd),
+      buffer_capacity_(buffer_capacity),
+      buffer_offset_(0u),
+      buffer_size_(0u),
+      total_byte_count_(0u) {
+  if (fd_ == -1) {
+    error_ = SystemErrorCodeToString(errno);
+  } else {
+    buffer_.reset(new uint8_t[buffer_capacity_]);
+  }
+}
+
+bool FileInputStream::Next(const void** data, size_t* size) {
+  if (HadError()) {
+    return false;
+  }
+
+  // Deal with any remaining bytes after BackUp was called.
+  if (buffer_offset_ != buffer_size_) {
+    *data = buffer_.get() + buffer_offset_;
+    *size = buffer_size_ - buffer_offset_;
+    total_byte_count_ += buffer_size_ - buffer_offset_;
+    buffer_offset_ = buffer_size_;
+    return true;
+  }
+
+  ssize_t n = TEMP_FAILURE_RETRY(read(fd_, buffer_.get(), buffer_capacity_));
+  if (n < 0) {
+    error_ = SystemErrorCodeToString(errno);
+    fd_.reset();
+    return false;
+  }
+
+  buffer_size_ = static_cast<size_t>(n);
+  buffer_offset_ = buffer_size_;
+  total_byte_count_ += buffer_size_;
+
+  *data = buffer_.get();
+  *size = buffer_size_;
+  return buffer_size_ != 0u;
+}
+
+void FileInputStream::BackUp(size_t count) {
+  if (count > buffer_offset_) {
+    count = buffer_offset_;
+  }
+  buffer_offset_ -= count;
+  total_byte_count_ -= count;
+}
+
+size_t FileInputStream::ByteCount() const {
+  return total_byte_count_;
+}
+
+bool FileInputStream::HadError() const {
+  return !error_.empty();
+}
+
+std::string FileInputStream::GetError() const {
+  return error_;
+}
+
+}  // namespace io
+}  // namespace aapt
diff --git a/tools/aapt2/io/FileInputStream.h b/tools/aapt2/io/FileInputStream.h
new file mode 100644
index 0000000..6beb9a1
--- /dev/null
+++ b/tools/aapt2/io/FileInputStream.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef AAPT_IO_FILEINPUTSTREAM_H
+#define AAPT_IO_FILEINPUTSTREAM_H
+
+#include "io/Io.h"
+
+#include <memory>
+#include <string>
+
+#include "android-base/macros.h"
+#include "android-base/unique_fd.h"
+
+namespace aapt {
+namespace io {
+
+class FileInputStream : public InputStream {
+ public:
+  explicit FileInputStream(const std::string& path, size_t buffer_capacity = 4096);
+
+  // Takes ownership of `fd`.
+  explicit FileInputStream(int fd, size_t buffer_capacity = 4096);
+
+  bool Next(const void** data, size_t* size) override;
+
+  void BackUp(size_t count) override;
+
+  size_t ByteCount() const override;
+
+  bool HadError() const override;
+
+  std::string GetError() const override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(FileInputStream);
+
+  android::base::unique_fd fd_;
+  std::string error_;
+  std::unique_ptr<uint8_t[]> buffer_;
+  size_t buffer_capacity_;
+  size_t buffer_offset_;
+  size_t buffer_size_;
+  size_t total_byte_count_;
+};
+
+}  // namespace io
+}  // namespace aapt
+
+#endif  // AAPT_IO_FILEINPUTSTREAM_H
diff --git a/tools/aapt2/io/FileInputStream_test.cpp b/tools/aapt2/io/FileInputStream_test.cpp
new file mode 100644
index 0000000..7314ab7
--- /dev/null
+++ b/tools/aapt2/io/FileInputStream_test.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include "io/FileInputStream.h"
+
+#include "android-base/macros.h"
+#include "android-base/test_utils.h"
+
+#include "test/Test.h"
+
+using ::android::StringPiece;
+using ::testing::Eq;
+using ::testing::NotNull;
+using ::testing::StrEq;
+
+namespace aapt {
+namespace io {
+
+TEST(FileInputStreamTest, NextAndBackup) {
+  std::string input = "this is a cool string";
+  TemporaryFile file;
+  ASSERT_THAT(TEMP_FAILURE_RETRY(write(file.fd, input.c_str(), input.size())), Eq(21));
+  lseek64(file.fd, 0, SEEK_SET);
+
+  // Use a small buffer size so that we can call Next() a few times.
+  FileInputStream in(file.fd, 10u);
+  ASSERT_FALSE(in.HadError());
+  EXPECT_THAT(in.ByteCount(), Eq(0u));
+
+  const char* buffer;
+  size_t size;
+  ASSERT_TRUE(in.Next(reinterpret_cast<const void**>(&buffer), &size)) << in.GetError();
+  ASSERT_THAT(size, Eq(10u));
+  ASSERT_THAT(buffer, NotNull());
+  EXPECT_THAT(in.ByteCount(), Eq(10u));
+  EXPECT_THAT(StringPiece(buffer, size), Eq("this is a "));
+
+  ASSERT_TRUE(in.Next(reinterpret_cast<const void**>(&buffer), &size));
+  ASSERT_THAT(size, Eq(10u));
+  ASSERT_THAT(buffer, NotNull());
+  EXPECT_THAT(in.ByteCount(), Eq(20u));
+  EXPECT_THAT(StringPiece(buffer, size), Eq("cool strin"));
+
+  in.BackUp(5u);
+  EXPECT_THAT(in.ByteCount(), Eq(15u));
+
+  ASSERT_TRUE(in.Next(reinterpret_cast<const void**>(&buffer), &size));
+  ASSERT_THAT(size, Eq(5u));
+  ASSERT_THAT(buffer, NotNull());
+  ASSERT_THAT(in.ByteCount(), Eq(20u));
+  EXPECT_THAT(StringPiece(buffer, size), Eq("strin"));
+
+  // Backup 1 more than possible. Should clamp.
+  in.BackUp(11u);
+  EXPECT_THAT(in.ByteCount(), Eq(10u));
+
+  ASSERT_TRUE(in.Next(reinterpret_cast<const void**>(&buffer), &size));
+  ASSERT_THAT(size, Eq(10u));
+  ASSERT_THAT(buffer, NotNull());
+  ASSERT_THAT(in.ByteCount(), Eq(20u));
+  EXPECT_THAT(StringPiece(buffer, size), Eq("cool strin"));
+
+  ASSERT_TRUE(in.Next(reinterpret_cast<const void**>(&buffer), &size));
+  ASSERT_THAT(size, Eq(1u));
+  ASSERT_THAT(buffer, NotNull());
+  ASSERT_THAT(in.ByteCount(), Eq(21u));
+  EXPECT_THAT(StringPiece(buffer, size), Eq("g"));
+
+  EXPECT_FALSE(in.Next(reinterpret_cast<const void**>(&buffer), &size));
+  EXPECT_FALSE(in.HadError());
+}
+
+}  // namespace io
+}  // namespace aapt
diff --git a/tools/aapt2/io/StringInputStream.cpp b/tools/aapt2/io/StringInputStream.cpp
new file mode 100644
index 0000000..51a18a7
--- /dev/null
+++ b/tools/aapt2/io/StringInputStream.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include "io/StringInputStream.h"
+
+using ::android::StringPiece;
+
+namespace aapt {
+namespace io {
+
+StringInputStream::StringInputStream(const StringPiece& str) : str_(str), offset_(0u) {
+}
+
+bool StringInputStream::Next(const void** data, size_t* size) {
+  if (offset_ == str_.size()) {
+    return false;
+  }
+
+  *data = str_.data() + offset_;
+  *size = str_.size() - offset_;
+  offset_ = str_.size();
+  return true;
+}
+
+void StringInputStream::BackUp(size_t count) {
+  if (count > offset_) {
+    count = offset_;
+  }
+  offset_ -= count;
+}
+
+size_t StringInputStream::ByteCount() const {
+  return offset_;
+}
+
+}  // namespace io
+}  // namespace aapt
diff --git a/tools/aapt2/io/StringInputStream.h b/tools/aapt2/io/StringInputStream.h
new file mode 100644
index 0000000..ff5b112
--- /dev/null
+++ b/tools/aapt2/io/StringInputStream.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef AAPT_IO_STRINGINPUTSTREAM_H
+#define AAPT_IO_STRINGINPUTSTREAM_H
+
+#include "io/Io.h"
+
+#include "android-base/macros.h"
+#include "androidfw/StringPiece.h"
+
+namespace aapt {
+namespace io {
+
+class StringInputStream : public InputStream {
+ public:
+  explicit StringInputStream(const android::StringPiece& str);
+
+  bool Next(const void** data, size_t* size) override;
+
+  void BackUp(size_t count) override;
+
+  size_t ByteCount() const override;
+
+  inline bool HadError() const override {
+    return false;
+  }
+
+  inline std::string GetError() const override {
+    return {};
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(StringInputStream);
+
+  android::StringPiece str_;
+  size_t offset_;
+};
+
+}  // namespace io
+}  // namespace aapt
+
+#endif  // AAPT_IO_STRINGINPUTSTREAM_H
diff --git a/tools/aapt2/io/StringInputStream_test.cpp b/tools/aapt2/io/StringInputStream_test.cpp
new file mode 100644
index 0000000..cc57bc4
--- /dev/null
+++ b/tools/aapt2/io/StringInputStream_test.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include "io/StringInputStream.h"
+
+#include "test/Test.h"
+
+using ::android::StringPiece;
+using ::testing::Eq;
+using ::testing::NotNull;
+using ::testing::StrEq;
+
+namespace aapt {
+namespace io {
+
+TEST(StringInputStreamTest, OneCallToNextShouldReturnEntireBuffer) {
+  constexpr const size_t kCount = 1000;
+  std::string input;
+  input.resize(kCount, 0x7f);
+  input[0] = 0x00;
+  input[kCount - 1] = 0xff;
+  StringInputStream in(input);
+
+  const char* buffer;
+  size_t size;
+  ASSERT_TRUE(in.Next(reinterpret_cast<const void**>(&buffer), &size));
+  ASSERT_THAT(size, Eq(kCount));
+  ASSERT_THAT(buffer, NotNull());
+
+  EXPECT_THAT(buffer[0], Eq(0x00));
+  EXPECT_THAT(buffer[kCount - 1], Eq('\xff'));
+
+  EXPECT_FALSE(in.Next(reinterpret_cast<const void**>(&buffer), &size));
+  EXPECT_FALSE(in.HadError());
+}
+
+TEST(StringInputStreamTest, BackUp) {
+  std::string input = "hello this is a string";
+  StringInputStream in(input);
+
+  const char* buffer;
+  size_t size;
+  ASSERT_TRUE(in.Next(reinterpret_cast<const void**>(&buffer), &size));
+  ASSERT_THAT(size, Eq(input.size()));
+  ASSERT_THAT(buffer, NotNull());
+  EXPECT_THAT(in.ByteCount(), Eq(input.size()));
+
+  in.BackUp(6u);
+  EXPECT_THAT(in.ByteCount(), Eq(input.size() - 6u));
+
+  ASSERT_TRUE(in.Next(reinterpret_cast<const void**>(&buffer), &size));
+  ASSERT_THAT(size, Eq(6u));
+  ASSERT_THAT(buffer, NotNull());
+  ASSERT_THAT(buffer, StrEq("string"));
+  EXPECT_THAT(in.ByteCount(), Eq(input.size()));
+}
+
+}  // namespace io
+}  // namespace aapt
diff --git a/tools/aapt2/java/ClassDefinition.cpp b/tools/aapt2/java/ClassDefinition.cpp
index 0cec9ae..d7508d2 100644
--- a/tools/aapt2/java/ClassDefinition.cpp
+++ b/tools/aapt2/java/ClassDefinition.cpp
@@ -39,6 +39,17 @@
   *out << prefix << "}";
 }
 
+ClassDefinition::Result ClassDefinition::AddMember(std::unique_ptr<ClassMember> member) {
+  Result result = Result::kAdded;
+  auto iter = members_.find(member);
+  if (iter != members_.end()) {
+    members_.erase(iter);
+    result = Result::kOverridden;
+  }
+  members_.insert(std::move(member));
+  return result;
+}
+
 bool ClassDefinition::empty() const {
   for (const std::unique_ptr<ClassMember>& member : members_) {
     if (!member->empty()) {
diff --git a/tools/aapt2/java/ClassDefinition.h b/tools/aapt2/java/ClassDefinition.h
index ca76421..6c4bcad 100644
--- a/tools/aapt2/java/ClassDefinition.h
+++ b/tools/aapt2/java/ClassDefinition.h
@@ -18,6 +18,7 @@
 #define AAPT_JAVA_CLASSDEFINITION_H
 
 #include <ostream>
+#include <set>
 #include <string>
 
 #include "android-base/macros.h"
@@ -37,10 +38,14 @@
  public:
   virtual ~ClassMember() = default;
 
-  AnnotationProcessor* GetCommentBuilder() { return &processor_; }
+  AnnotationProcessor* GetCommentBuilder() {
+    return &processor_;
+  }
 
   virtual bool empty() const = 0;
 
+  virtual const std::string& GetName() const = 0;
+
   // Writes the class member to the out stream. Subclasses should derive this method
   // to write their own data. Call this base method from the subclass to write out
   // this member's comments/annotations.
@@ -57,7 +62,13 @@
   PrimitiveMember(const android::StringPiece& name, const T& val)
       : name_(name.to_string()), val_(val) {}
 
-  bool empty() const override { return false; }
+  bool empty() const override {
+    return false;
+  }
+
+  const std::string& GetName() const override {
+    return name_;
+  }
 
   void WriteToStream(const android::StringPiece& prefix, bool final,
                      std::ostream* out) const override {
@@ -83,7 +94,13 @@
   PrimitiveMember(const android::StringPiece& name, const std::string& val)
       : name_(name.to_string()), val_(val) {}
 
-  bool empty() const override { return false; }
+  bool empty() const override {
+    return false;
+  }
+
+  const std::string& GetName() const override {
+    return name_;
+  }
 
   void WriteToStream(const android::StringPiece& prefix, bool final,
                      std::ostream* out) const override {
@@ -109,9 +126,17 @@
  public:
   explicit PrimitiveArrayMember(const android::StringPiece& name) : name_(name.to_string()) {}
 
-  void AddElement(const T& val) { elements_.push_back(val); }
+  void AddElement(const T& val) {
+    elements_.push_back(val);
+  }
 
-  bool empty() const override { return false; }
+  bool empty() const override {
+    return false;
+  }
+
+  const std::string& GetName() const override {
+    return name_;
+  }
 
   void WriteToStream(const android::StringPiece& prefix, bool final,
                      std::ostream* out) const override {
@@ -154,6 +179,11 @@
   // formatting may be broken.
   void AppendStatement(const android::StringPiece& statement);
 
+  // Not quite the same as a name, but good enough.
+  const std::string& GetName() const override {
+    return signature_;
+  }
+
   // Even if the method is empty, we always want to write the method signature.
   bool empty() const override { return false; }
 
@@ -175,19 +205,34 @@
   ClassDefinition(const android::StringPiece& name, ClassQualifier qualifier, bool createIfEmpty)
       : name_(name.to_string()), qualifier_(qualifier), create_if_empty_(createIfEmpty) {}
 
-  void AddMember(std::unique_ptr<ClassMember> member) {
-    members_.push_back(std::move(member));
-  }
+  enum class Result {
+    kAdded,
+    kOverridden,
+  };
+
+  Result AddMember(std::unique_ptr<ClassMember> member);
 
   bool empty() const override;
+
+  const std::string& GetName() const override {
+    return name_;
+  }
+
   void WriteToStream(const android::StringPiece& prefix, bool final,
                      std::ostream* out) const override;
 
  private:
+  struct ClassMemberCompare {
+    using T = std::unique_ptr<ClassMember>;
+    bool operator()(const T& a, const T& b) const {
+      return a->GetName() < b->GetName();
+    }
+  };
+
   std::string name_;
   ClassQualifier qualifier_;
   bool create_if_empty_;
-  std::vector<std::unique_ptr<ClassMember>> members_;
+  std::set<std::unique_ptr<ClassMember>, ClassMemberCompare> members_;
 
   DISALLOW_COPY_AND_ASSIGN(ClassDefinition);
 };
diff --git a/tools/aapt2/java/ManifestClassGenerator.cpp b/tools/aapt2/java/ManifestClassGenerator.cpp
index f49e498..cad4c6c 100644
--- a/tools/aapt2/java/ManifestClassGenerator.cpp
+++ b/tools/aapt2/java/ManifestClassGenerator.cpp
@@ -81,7 +81,10 @@
       util::make_unique<StringMember>(result.value(), attr->value);
   string_member->GetCommentBuilder()->AppendComment(el->comment);
 
-  class_def->AddMember(std::move(string_member));
+  if (class_def->AddMember(std::move(string_member)) == ClassDefinition::Result::kOverridden) {
+    diag->Warn(DiagMessage(source.WithLine(el->line_number))
+               << "duplicate definitions of '" << result.value() << "', overriding previous");
+  }
   return true;
 }
 
diff --git a/tools/aapt2/java/ManifestClassGenerator_test.cpp b/tools/aapt2/java/ManifestClassGenerator_test.cpp
index 9f6ec21..44b6a1f 100644
--- a/tools/aapt2/java/ManifestClassGenerator_test.cpp
+++ b/tools/aapt2/java/ManifestClassGenerator_test.cpp
@@ -112,6 +112,21 @@
   EXPECT_THAT(actual, HasSubstr(expected_secret));
 }
 
+// This is bad but part of public API behaviour so we need to preserve it.
+TEST(ManifestClassGeneratorTest, LastSeenPermissionWithSameLeafNameTakesPrecedence) {
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+  std::unique_ptr<xml::XmlResource> manifest = test::BuildXmlDom(R"(
+      <manifest xmlns:android="http://schemas.android.com/apk/res/android">
+        <permission android:name="android.permission.ACCESS_INTERNET" />
+        <permission android:name="com.android.aapt.test.ACCESS_INTERNET" />
+      </manifest>)");
+
+  std::string actual;
+  ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), &actual));
+  EXPECT_THAT(actual, HasSubstr("ACCESS_INTERNET=\"com.android.aapt.test.ACCESS_INTERNET\";"));
+  EXPECT_THAT(actual, Not(HasSubstr("ACCESS_INTERNET=\"android.permission.ACCESS_INTERNET\";")));
+}
+
 static ::testing::AssertionResult GetManifestClassText(IAaptContext* context, xml::XmlResource* res,
                                                        std::string* out_str) {
   std::unique_ptr<ClassDefinition> manifest_class =
diff --git a/tools/aapt2/java/ProguardRules.cpp b/tools/aapt2/java/ProguardRules.cpp
index 5f61fae..10c4610 100644
--- a/tools/aapt2/java/ProguardRules.cpp
+++ b/tools/aapt2/java/ProguardRules.cpp
@@ -29,18 +29,12 @@
 
 class BaseVisitor : public xml::Visitor {
  public:
-  BaseVisitor(const Source& source, KeepSet* keep_set)
-      : source_(source), keep_set_(keep_set) {}
+  using xml::Visitor::Visit;
 
-  virtual void Visit(xml::Text*) override{};
-
-  virtual void Visit(xml::Namespace* node) override {
-    for (const auto& child : node->children) {
-      child->Accept(this);
-    }
+  BaseVisitor(const Source& source, KeepSet* keep_set) : source_(source), keep_set_(keep_set) {
   }
 
-  virtual void Visit(xml::Element* node) override {
+  void Visit(xml::Element* node) override {
     if (!node->namespace_uri.empty()) {
       Maybe<xml::ExtractedPackage> maybe_package =
           xml::ExtractPackageFromNamespace(node->namespace_uri);
@@ -78,10 +72,10 @@
 
 class LayoutVisitor : public BaseVisitor {
  public:
-  LayoutVisitor(const Source& source, KeepSet* keep_set)
-      : BaseVisitor(source, keep_set) {}
+  LayoutVisitor(const Source& source, KeepSet* keep_set) : BaseVisitor(source, keep_set) {
+  }
 
-  virtual void Visit(xml::Element* node) override {
+  void Visit(xml::Element* node) override {
     bool check_class = false;
     bool check_name = false;
     if (node->namespace_uri.empty()) {
@@ -119,7 +113,7 @@
   MenuVisitor(const Source& source, KeepSet* keep_set) : BaseVisitor(source, keep_set) {
   }
 
-  virtual void Visit(xml::Element* node) override {
+  void Visit(xml::Element* node) override {
     if (node->namespace_uri.empty() && node->name == "item") {
       for (const auto& attr : node->attributes) {
         if (attr.namespace_uri == xml::kSchemaAndroid) {
@@ -142,10 +136,10 @@
 
 class XmlResourceVisitor : public BaseVisitor {
  public:
-  XmlResourceVisitor(const Source& source, KeepSet* keep_set)
-      : BaseVisitor(source, keep_set) {}
+  XmlResourceVisitor(const Source& source, KeepSet* keep_set) : BaseVisitor(source, keep_set) {
+  }
 
-  virtual void Visit(xml::Element* node) override {
+  void Visit(xml::Element* node) override {
     bool check_fragment = false;
     if (node->namespace_uri.empty()) {
       check_fragment =
@@ -169,13 +163,12 @@
 
 class TransitionVisitor : public BaseVisitor {
  public:
-  TransitionVisitor(const Source& source, KeepSet* keep_set)
-      : BaseVisitor(source, keep_set) {}
+  TransitionVisitor(const Source& source, KeepSet* keep_set) : BaseVisitor(source, keep_set) {
+  }
 
-  virtual void Visit(xml::Element* node) override {
+  void Visit(xml::Element* node) override {
     bool check_class =
-        node->namespace_uri.empty() &&
-        (node->name == "transition" || node->name == "pathMotion");
+        node->namespace_uri.empty() && (node->name == "transition" || node->name == "pathMotion");
     if (check_class) {
       xml::Attribute* attr = node->FindAttribute({}, "class");
       if (attr && util::IsJavaClassName(attr->value)) {
@@ -195,7 +188,7 @@
   ManifestVisitor(const Source& source, KeepSet* keep_set, bool main_dex_only)
       : BaseVisitor(source, keep_set), main_dex_only_(main_dex_only) {}
 
-  virtual void Visit(xml::Element* node) override {
+  void Visit(xml::Element* node) override {
     if (node->namespace_uri.empty()) {
       bool get_name = false;
       if (node->name == "manifest") {
@@ -205,18 +198,15 @@
         }
       } else if (node->name == "application") {
         get_name = true;
-        xml::Attribute* attr =
-            node->FindAttribute(xml::kSchemaAndroid, "backupAgent");
+        xml::Attribute* attr = node->FindAttribute(xml::kSchemaAndroid, "backupAgent");
         if (attr) {
-          Maybe<std::string> result =
-              util::GetFullyQualifiedClassName(package_, attr->value);
+          Maybe<std::string> result = util::GetFullyQualifiedClassName(package_, attr->value);
           if (result) {
             AddClass(node->line_number, result.value());
           }
         }
         if (main_dex_only_) {
-          xml::Attribute* default_process =
-              node->FindAttribute(xml::kSchemaAndroid, "process");
+          xml::Attribute* default_process = node->FindAttribute(xml::kSchemaAndroid, "process");
           if (default_process) {
             default_process_ = default_process->value;
           }
@@ -226,8 +216,7 @@
         get_name = true;
 
         if (main_dex_only_) {
-          xml::Attribute* component_process =
-              node->FindAttribute(xml::kSchemaAndroid, "process");
+          xml::Attribute* component_process = node->FindAttribute(xml::kSchemaAndroid, "process");
 
           const std::string& process =
               component_process ? component_process->value : default_process_;
@@ -242,8 +231,7 @@
         get_name = attr != nullptr;
 
         if (get_name) {
-          Maybe<std::string> result =
-              util::GetFullyQualifiedClassName(package_, attr->value);
+          Maybe<std::string> result = util::GetFullyQualifiedClassName(package_, attr->value);
           if (result) {
             AddClass(node->line_number, result.value());
           }
@@ -261,8 +249,7 @@
   std::string default_process_;
 };
 
-bool CollectProguardRulesForManifest(const Source& source,
-                                     xml::XmlResource* res, KeepSet* keep_set,
+bool CollectProguardRulesForManifest(const Source& source, xml::XmlResource* res, KeepSet* keep_set,
                                      bool main_dex_only) {
   ManifestVisitor visitor(source, keep_set, main_dex_only);
   if (res->root) {
@@ -272,8 +259,7 @@
   return false;
 }
 
-bool CollectProguardRules(const Source& source, xml::XmlResource* res,
-                          KeepSet* keep_set) {
+bool CollectProguardRules(const Source& source, xml::XmlResource* res, KeepSet* keep_set) {
   if (!res->root) {
     return false;
   }
@@ -321,8 +307,7 @@
     for (const Source& source : entry.second) {
       *out << "# Referenced at " << source << "\n";
     }
-    *out << "-keepclassmembers class * { *** " << entry.first << "(...); }\n"
-         << std::endl;
+    *out << "-keepclassmembers class * { *** " << entry.first << "(...); }\n" << std::endl;
   }
   return true;
 }
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index 80edb35..da7f410 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -122,7 +122,7 @@
   xml::Element* el;
   xml::Attribute* attr;
 
-  el = xml::FindRootElement(doc.get());
+  el = doc->root.get();
   ASSERT_NE(nullptr, el);
   el = el->FindChild({}, "uses-sdk");
   ASSERT_NE(nullptr, el);
@@ -141,7 +141,7 @@
                           options);
   ASSERT_NE(nullptr, doc);
 
-  el = xml::FindRootElement(doc.get());
+  el = doc->root.get();
   ASSERT_NE(nullptr, el);
   el = el->FindChild({}, "uses-sdk");
   ASSERT_NE(nullptr, el);
@@ -160,7 +160,7 @@
                           options);
   ASSERT_NE(nullptr, doc);
 
-  el = xml::FindRootElement(doc.get());
+  el = doc->root.get();
   ASSERT_NE(nullptr, el);
   el = el->FindChild({}, "uses-sdk");
   ASSERT_NE(nullptr, el);
@@ -177,7 +177,7 @@
                           options);
   ASSERT_NE(nullptr, doc);
 
-  el = xml::FindRootElement(doc.get());
+  el = doc->root.get();
   ASSERT_NE(nullptr, el);
   el = el->FindChild({}, "uses-sdk");
   ASSERT_NE(nullptr, el);
@@ -199,7 +199,7 @@
                                                             options);
   ASSERT_NE(nullptr, doc);
 
-  xml::Element* manifest_el = xml::FindRootElement(doc.get());
+  xml::Element* manifest_el = doc->root.get();
   ASSERT_NE(nullptr, manifest_el);
   ASSERT_EQ("manifest", manifest_el->name);
 
@@ -248,7 +248,7 @@
                                                             options);
   ASSERT_NE(nullptr, doc);
 
-  xml::Element* manifestEl = xml::FindRootElement(doc.get());
+  xml::Element* manifestEl = doc->root.get();
   ASSERT_NE(nullptr, manifestEl);
 
   xml::Attribute* attr = nullptr;
@@ -297,7 +297,7 @@
                                                             options);
   ASSERT_NE(nullptr, doc);
 
-  xml::Element* manifest_el = xml::FindRootElement(doc.get());
+  xml::Element* manifest_el = doc->root.get();
   ASSERT_NE(nullptr, manifest_el);
 
   xml::Element* instrumentation_el =
@@ -321,7 +321,7 @@
                                                             options);
   ASSERT_NE(nullptr, doc);
 
-  xml::Element* manifest_el = xml::FindRootElement(doc.get());
+  xml::Element* manifest_el = doc->root.get();
   ASSERT_NE(nullptr, manifest_el);
 
   xml::Attribute* attr =
@@ -344,7 +344,7 @@
       Verify("<manifest package=\"android\" coreApp=\"true\" />");
   ASSERT_NE(nullptr, doc);
 
-  xml::Element* el = xml::FindRootElement(doc.get());
+  xml::Element* el = doc->root.get();
   ASSERT_NE(nullptr, el);
 
   EXPECT_EQ("manifest", el->name);
diff --git a/tools/aapt2/link/XmlCompatVersioner.cpp b/tools/aapt2/link/XmlCompatVersioner.cpp
index f1f4e3b..20ebdc6 100644
--- a/tools/aapt2/link/XmlCompatVersioner.cpp
+++ b/tools/aapt2/link/XmlCompatVersioner.cpp
@@ -107,7 +107,7 @@
   std::unique_ptr<xml::XmlResource> cloned_doc = util::make_unique<xml::XmlResource>(doc->file);
   cloned_doc->file.config.sdkVersion = static_cast<uint16_t>(target_api);
 
-  cloned_doc->root = doc->root->Clone([&](const xml::Element& el, xml::Element* out_el) {
+  cloned_doc->root = doc->root->CloneElement([&](const xml::Element& el, xml::Element* out_el) {
     for (const auto& attr : el.attributes) {
       if (!attr.compiled_attribute) {
         // Just copy if this isn't a compiled attribute.
diff --git a/tools/aapt2/link/XmlCompatVersioner_test.cpp b/tools/aapt2/link/XmlCompatVersioner_test.cpp
index ce6605c..29ad25f 100644
--- a/tools/aapt2/link/XmlCompatVersioner_test.cpp
+++ b/tools/aapt2/link/XmlCompatVersioner_test.cpp
@@ -19,6 +19,12 @@
 #include "Linkers.h"
 #include "test/Test.h"
 
+using ::aapt::test::ValueEq;
+using ::testing::Eq;
+using ::testing::IsNull;
+using ::testing::NotNull;
+using ::testing::SizeIs;
+
 namespace aapt {
 
 constexpr auto TYPE_DIMENSION = android::ResTable_map::TYPE_DIMENSION;
@@ -68,12 +74,12 @@
 };
 
 TEST_F(XmlCompatVersionerTest, NoRulesOnlyStripsAndCopies) {
-  auto doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF(
+  auto doc = test::BuildXmlDomForPackageName(context_.get(), R"(
       <View xmlns:android="http://schemas.android.com/apk/res/android"
           xmlns:app="http://schemas.android.com/apk/res-auto"
           android:paddingHorizontal="24dp"
           app:foo="16dp"
-          foo="bar"/>)EOF");
+          foo="bar"/>)");
 
   XmlReferenceLinker linker;
   ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
@@ -84,35 +90,35 @@
   XmlCompatVersioner versioner(&rules);
   std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs =
       versioner.Process(context_.get(), doc.get(), api_range);
-  ASSERT_EQ(2u, versioned_docs.size());
+  ASSERT_THAT(versioned_docs, SizeIs(2u));
 
   xml::Element* el;
 
   // Source XML file's sdkVersion == 0, so the first one must also have the same sdkVersion.
-  EXPECT_EQ(static_cast<uint16_t>(0), versioned_docs[0]->file.config.sdkVersion);
-  el = xml::FindRootElement(versioned_docs[0].get());
-  ASSERT_NE(nullptr, el);
-  EXPECT_EQ(2u, el->attributes.size());
-  EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"));
-  EXPECT_NE(nullptr, el->FindAttribute(xml::kSchemaAuto, "foo"));
-  EXPECT_NE(nullptr, el->FindAttribute({}, "foo"));
+  EXPECT_THAT(versioned_docs[0]->file.config.sdkVersion, Eq(0u));
+  el = versioned_docs[0]->root.get();
+  ASSERT_THAT(el, NotNull());
+  EXPECT_THAT(el->attributes, SizeIs(2u));
+  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), IsNull());
+  EXPECT_THAT(el->FindAttribute(xml::kSchemaAuto, "foo"), NotNull());
+  EXPECT_THAT(el->FindAttribute({}, "foo"), NotNull());
 
-  EXPECT_EQ(static_cast<uint16_t>(SDK_LOLLIPOP_MR1), versioned_docs[1]->file.config.sdkVersion);
-  el = xml::FindRootElement(versioned_docs[1].get());
-  ASSERT_NE(nullptr, el);
-  EXPECT_EQ(3u, el->attributes.size());
-  EXPECT_NE(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"));
-  EXPECT_NE(nullptr, el->FindAttribute(xml::kSchemaAuto, "foo"));
-  EXPECT_NE(nullptr, el->FindAttribute({}, "foo"));
+  EXPECT_THAT(versioned_docs[1]->file.config.sdkVersion, Eq(SDK_LOLLIPOP_MR1));
+  el = versioned_docs[1]->root.get();
+  ASSERT_THAT(el, NotNull());
+  EXPECT_THAT(el->attributes, SizeIs(3u));
+  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), NotNull());
+  EXPECT_THAT(el->FindAttribute(xml::kSchemaAuto, "foo"), NotNull());
+  EXPECT_THAT(el->FindAttribute({}, "foo"), NotNull());
 }
 
 TEST_F(XmlCompatVersionerTest, SingleRule) {
-  auto doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF(
+  auto doc = test::BuildXmlDomForPackageName(context_.get(), R"(
       <View xmlns:android="http://schemas.android.com/apk/res/android"
           xmlns:app="http://schemas.android.com/apk/res-auto"
           android:paddingHorizontal="24dp"
           app:foo="16dp"
-          foo="bar"/>)EOF");
+          foo="bar"/>)");
 
   XmlReferenceLinker linker;
   ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
@@ -129,51 +135,51 @@
   XmlCompatVersioner versioner(&rules);
   std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs =
       versioner.Process(context_.get(), doc.get(), api_range);
-  ASSERT_EQ(2u, versioned_docs.size());
+  ASSERT_THAT(versioned_docs, SizeIs(2u));
 
   xml::Element* el;
 
-  EXPECT_EQ(static_cast<uint16_t>(0), versioned_docs[0]->file.config.sdkVersion);
-  el = xml::FindRootElement(versioned_docs[0].get());
-  ASSERT_NE(nullptr, el);
-  EXPECT_EQ(4u, el->attributes.size());
-  EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"));
-  EXPECT_NE(nullptr, el->FindAttribute(xml::kSchemaAuto, "foo"));
-  EXPECT_NE(nullptr, el->FindAttribute({}, "foo"));
+  EXPECT_THAT(versioned_docs[0]->file.config.sdkVersion, Eq(0u));
+  el = versioned_docs[0]->root.get();
+  ASSERT_THAT(el, NotNull());
+  EXPECT_THAT(el->attributes, SizeIs(4u));
+  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), IsNull());
+  EXPECT_THAT(el->FindAttribute(xml::kSchemaAuto, "foo"), NotNull());
+  EXPECT_THAT(el->FindAttribute({}, "foo"), NotNull());
 
   xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft");
-  ASSERT_NE(nullptr, attr);
-  ASSERT_NE(nullptr, attr->compiled_value);
+  ASSERT_THAT(attr, NotNull());
+  ASSERT_THAT(attr->compiled_value, NotNull());
   ASSERT_TRUE(attr->compiled_attribute);
 
   attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight");
-  ASSERT_NE(nullptr, attr);
-  ASSERT_NE(nullptr, attr->compiled_value);
+  ASSERT_THAT(attr, NotNull());
+  ASSERT_THAT(attr->compiled_value, NotNull());
   ASSERT_TRUE(attr->compiled_attribute);
 
-  EXPECT_EQ(static_cast<uint16_t>(SDK_LOLLIPOP_MR1), versioned_docs[1]->file.config.sdkVersion);
-  el = xml::FindRootElement(versioned_docs[1].get());
-  ASSERT_NE(nullptr, el);
-  EXPECT_EQ(5u, el->attributes.size());
-  EXPECT_NE(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"));
-  EXPECT_NE(nullptr, el->FindAttribute(xml::kSchemaAuto, "foo"));
-  EXPECT_NE(nullptr, el->FindAttribute({}, "foo"));
+  EXPECT_THAT(versioned_docs[1]->file.config.sdkVersion, Eq(SDK_LOLLIPOP_MR1));
+  el = versioned_docs[1]->root.get();
+  ASSERT_THAT(el, NotNull());
+  EXPECT_THAT(el->attributes, SizeIs(5u));
+  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), NotNull());
+  EXPECT_THAT(el->FindAttribute(xml::kSchemaAuto, "foo"), NotNull());
+  EXPECT_THAT(el->FindAttribute({}, "foo"), NotNull());
 
   attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft");
-  ASSERT_NE(nullptr, attr);
-  ASSERT_NE(nullptr, attr->compiled_value);
+  ASSERT_THAT(attr, NotNull());
+  ASSERT_THAT(attr->compiled_value, NotNull());
   ASSERT_TRUE(attr->compiled_attribute);
 
   attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight");
-  ASSERT_NE(nullptr, attr);
-  ASSERT_NE(nullptr, attr->compiled_value);
+  ASSERT_THAT(attr, NotNull());
+  ASSERT_THAT(attr->compiled_value, NotNull());
   ASSERT_TRUE(attr->compiled_attribute);
 }
 
 TEST_F(XmlCompatVersionerTest, ChainedRule) {
-  auto doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF(
+  auto doc = test::BuildXmlDomForPackageName(context_.get(), R"(
       <View xmlns:android="http://schemas.android.com/apk/res/android"
-          android:paddingHorizontal="24dp" />)EOF");
+          android:paddingHorizontal="24dp" />)");
 
   XmlReferenceLinker linker;
   ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
@@ -193,71 +199,70 @@
   XmlCompatVersioner versioner(&rules);
   std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs =
       versioner.Process(context_.get(), doc.get(), api_range);
-  ASSERT_EQ(3u, versioned_docs.size());
+  ASSERT_THAT(versioned_docs, SizeIs(3u));
 
   xml::Element* el;
 
-  EXPECT_EQ(static_cast<uint16_t>(0), versioned_docs[0]->file.config.sdkVersion);
-  el = xml::FindRootElement(versioned_docs[0].get());
-  ASSERT_NE(nullptr, el);
-  EXPECT_EQ(2u, el->attributes.size());
-  EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"));
+  EXPECT_THAT(versioned_docs[0]->file.config.sdkVersion, Eq(0u));
+  el = versioned_docs[0]->root.get();
+  ASSERT_THAT(el, NotNull());
+  EXPECT_THAT(el->attributes, SizeIs(2u));
+  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), IsNull());
 
   xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft");
-  ASSERT_NE(nullptr, attr);
-  ASSERT_NE(nullptr, attr->compiled_value);
+  ASSERT_THAT(attr, NotNull());
+  ASSERT_THAT(attr->compiled_value, NotNull());
   ASSERT_TRUE(attr->compiled_attribute);
 
   attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight");
-  ASSERT_NE(nullptr, attr);
-  ASSERT_NE(nullptr, attr->compiled_value);
+  ASSERT_THAT(attr, NotNull());
+  ASSERT_THAT(attr->compiled_value, NotNull());
   ASSERT_TRUE(attr->compiled_attribute);
 
-  EXPECT_EQ(static_cast<uint16_t>(SDK_HONEYCOMB), versioned_docs[1]->file.config.sdkVersion);
-  el = xml::FindRootElement(versioned_docs[1].get());
-  ASSERT_NE(nullptr, el);
-  EXPECT_EQ(1u, el->attributes.size());
-  EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"));
-  EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingLeft"));
-  EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingRight"));
+  EXPECT_THAT(versioned_docs[1]->file.config.sdkVersion, Eq(SDK_HONEYCOMB));
+  el = versioned_docs[1]->root.get();
+  ASSERT_THAT(el, NotNull());
+  EXPECT_THAT(el->attributes, SizeIs(1u));
+  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), IsNull());
+  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingLeft"), IsNull());
+  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingRight"), IsNull());
 
   attr = el->FindAttribute(xml::kSchemaAndroid, "progressBarPadding");
-  ASSERT_NE(nullptr, attr);
-  ASSERT_NE(nullptr, attr->compiled_value);
+  ASSERT_THAT(attr, NotNull());
+  ASSERT_THAT(attr->compiled_value, NotNull());
   ASSERT_TRUE(attr->compiled_attribute);
 
-  EXPECT_EQ(static_cast<uint16_t>(SDK_LOLLIPOP_MR1), versioned_docs[2]->file.config.sdkVersion);
-  el = xml::FindRootElement(versioned_docs[2].get());
-  ASSERT_NE(nullptr, el);
-  EXPECT_EQ(2u, el->attributes.size());
-  EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingLeft"));
-  EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingRight"));
+  EXPECT_THAT(versioned_docs[2]->file.config.sdkVersion, Eq(SDK_LOLLIPOP_MR1));
+  el = versioned_docs[2]->root.get();
+  ASSERT_THAT(el, NotNull());
+  EXPECT_THAT(el->attributes, SizeIs(2u));
+  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingLeft"), IsNull());
+  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingRight"), IsNull());
 
   attr = el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal");
-  ASSERT_NE(nullptr, attr);
-  ASSERT_NE(nullptr, attr->compiled_value);
+  ASSERT_THAT(attr, NotNull());
+  ASSERT_THAT(attr->compiled_value, NotNull());
   ASSERT_TRUE(attr->compiled_attribute);
 
   attr = el->FindAttribute(xml::kSchemaAndroid, "progressBarPadding");
-  ASSERT_NE(nullptr, attr);
-  ASSERT_NE(nullptr, attr->compiled_value);
+  ASSERT_THAT(attr, NotNull());
+  ASSERT_THAT(attr->compiled_value, NotNull());
   ASSERT_TRUE(attr->compiled_attribute);
 }
 
 TEST_F(XmlCompatVersionerTest, DegradeRuleOverridesExistingAttribute) {
-  auto doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF(
+  auto doc = test::BuildXmlDomForPackageName(context_.get(), R"(
       <View xmlns:android="http://schemas.android.com/apk/res/android"
           android:paddingHorizontal="24dp"
           android:paddingLeft="16dp"
-          android:paddingRight="16dp"/>)EOF");
+          android:paddingRight="16dp"/>)");
 
   XmlReferenceLinker linker;
   ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
 
-  Item* padding_horizontal_value = xml::FindRootElement(doc.get())
-                                       ->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal")
-                                       ->compiled_value.get();
-  ASSERT_NE(nullptr, padding_horizontal_value);
+  Item* padding_horizontal_value =
+      doc->root->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal")->compiled_value.get();
+  ASSERT_THAT(padding_horizontal_value, NotNull());
 
   XmlCompatVersioner::Rules rules;
   rules[R::attr::paddingHorizontal] =
@@ -271,50 +276,50 @@
   XmlCompatVersioner versioner(&rules);
   std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs =
       versioner.Process(context_.get(), doc.get(), api_range);
-  ASSERT_EQ(2u, versioned_docs.size());
+  ASSERT_THAT(versioned_docs, SizeIs(2u));
 
   xml::Element* el;
 
-  EXPECT_EQ(static_cast<uint16_t>(0), versioned_docs[0]->file.config.sdkVersion);
-  el = xml::FindRootElement(versioned_docs[0].get());
-  ASSERT_NE(nullptr, el);
-  EXPECT_EQ(2u, el->attributes.size());
-  EXPECT_EQ(nullptr, el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"));
+  EXPECT_THAT(versioned_docs[0]->file.config.sdkVersion, Eq(0u));
+  el = versioned_docs[0]->root.get();
+  ASSERT_THAT(el, NotNull());
+  EXPECT_THAT(el->attributes, SizeIs(2u));
+  EXPECT_THAT(el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal"), IsNull());
 
   xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft");
-  ASSERT_NE(nullptr, attr);
-  ASSERT_NE(nullptr, attr->compiled_value);
-  ASSERT_TRUE(padding_horizontal_value->Equals(attr->compiled_value.get()));
+  ASSERT_THAT(attr, NotNull());
+  ASSERT_THAT(attr->compiled_value, NotNull());
   ASSERT_TRUE(attr->compiled_attribute);
+  ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
 
   attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight");
-  ASSERT_NE(nullptr, attr);
-  ASSERT_NE(nullptr, attr->compiled_value);
-  ASSERT_TRUE(padding_horizontal_value->Equals(attr->compiled_value.get()));
+  ASSERT_THAT(attr, NotNull());
+  ASSERT_THAT(attr->compiled_value, NotNull());
   ASSERT_TRUE(attr->compiled_attribute);
+  ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
 
-  EXPECT_EQ(static_cast<uint16_t>(SDK_LOLLIPOP_MR1), versioned_docs[1]->file.config.sdkVersion);
-  el = xml::FindRootElement(versioned_docs[1].get());
-  ASSERT_NE(nullptr, el);
-  EXPECT_EQ(3u, el->attributes.size());
+  EXPECT_THAT(versioned_docs[1]->file.config.sdkVersion, Eq(SDK_LOLLIPOP_MR1));
+  el = versioned_docs[1]->root.get();
+  ASSERT_THAT(el, NotNull());
+  EXPECT_THAT(el->attributes, SizeIs(3u));
 
   attr = el->FindAttribute(xml::kSchemaAndroid, "paddingHorizontal");
-  ASSERT_NE(nullptr, attr);
-  ASSERT_NE(nullptr, attr->compiled_value);
-  ASSERT_TRUE(padding_horizontal_value->Equals(attr->compiled_value.get()));
+  ASSERT_THAT(attr, NotNull());
+  ASSERT_THAT(attr->compiled_value, NotNull());
   ASSERT_TRUE(attr->compiled_attribute);
+  ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
 
   attr = el->FindAttribute(xml::kSchemaAndroid, "paddingLeft");
-  ASSERT_NE(nullptr, attr);
-  ASSERT_NE(nullptr, attr->compiled_value);
-  ASSERT_TRUE(padding_horizontal_value->Equals(attr->compiled_value.get()));
+  ASSERT_THAT(attr, NotNull());
+  ASSERT_THAT(attr->compiled_value, NotNull());
   ASSERT_TRUE(attr->compiled_attribute);
+  ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
 
   attr = el->FindAttribute(xml::kSchemaAndroid, "paddingRight");
-  ASSERT_NE(nullptr, attr);
-  ASSERT_NE(nullptr, attr->compiled_value);
-  ASSERT_TRUE(padding_horizontal_value->Equals(attr->compiled_value.get()));
+  ASSERT_THAT(attr, NotNull());
+  ASSERT_THAT(attr->compiled_value, NotNull());
   ASSERT_TRUE(attr->compiled_attribute);
+  ASSERT_THAT(*attr->compiled_value, ValueEq(padding_horizontal_value));
 }
 
 }  // namespace aapt
diff --git a/tools/aapt2/link/XmlNamespaceRemover.cpp b/tools/aapt2/link/XmlNamespaceRemover.cpp
index 24aa566..b5e2423 100644
--- a/tools/aapt2/link/XmlNamespaceRemover.cpp
+++ b/tools/aapt2/link/XmlNamespaceRemover.cpp
@@ -24,37 +24,19 @@
 
 namespace {
 
-/**
- * Visits each xml Node, removing URI references and nested namespaces.
- */
+// Visits each xml Node, removing URI references and nested namespaces.
 class XmlVisitor : public xml::Visitor {
  public:
   explicit XmlVisitor(bool keep_uris) : keep_uris_(keep_uris) {}
 
   void Visit(xml::Element* el) override {
-    // Strip namespaces
-    for (auto& child : el->children) {
-      while (child && xml::NodeCast<xml::Namespace>(child.get())) {
-        if (child->children.empty()) {
-          child = {};
-        } else {
-          child = std::move(child->children.front());
-          child->parent = el;
-        }
-      }
-    }
-    el->children.erase(
-        std::remove_if(el->children.begin(), el->children.end(),
-                       [](const std::unique_ptr<xml::Node>& child) -> bool {
-                         return child == nullptr;
-                       }),
-        el->children.end());
+    el->namespace_decls.clear();
 
     if (!keep_uris_) {
       for (xml::Attribute& attr : el->attributes) {
-        attr.namespace_uri = std::string();
+        attr.namespace_uri.clear();
       }
-      el->namespace_uri = std::string();
+      el->namespace_uri.clear();
     }
     xml::Visitor::Visit(el);
   }
@@ -67,19 +49,11 @@
 
 }  // namespace
 
-bool XmlNamespaceRemover::Consume(IAaptContext* context,
-                                  xml::XmlResource* resource) {
+bool XmlNamespaceRemover::Consume(IAaptContext* context, xml::XmlResource* resource) {
   if (!resource->root) {
     return false;
   }
-  // Replace any root namespaces until the root is a non-namespace node
-  while (xml::NodeCast<xml::Namespace>(resource->root.get())) {
-    if (resource->root->children.empty()) {
-      break;
-    }
-    resource->root = std::move(resource->root->children.front());
-    resource->root->parent = nullptr;
-  }
+
   XmlVisitor visitor(keep_uris_);
   resource->root->Accept(&visitor);
   return true;
diff --git a/tools/aapt2/link/XmlNamespaceRemover_test.cpp b/tools/aapt2/link/XmlNamespaceRemover_test.cpp
index a176c03..df4920f 100644
--- a/tools/aapt2/link/XmlNamespaceRemover_test.cpp
+++ b/tools/aapt2/link/XmlNamespaceRemover_test.cpp
@@ -18,6 +18,10 @@
 
 #include "test/Test.h"
 
+using ::testing::NotNull;
+using ::testing::SizeIs;
+using ::testing::StrEq;
+
 namespace aapt {
 
 class XmlUriTestVisitor : public xml::Visitor {
@@ -25,16 +29,14 @@
   XmlUriTestVisitor() = default;
 
   void Visit(xml::Element* el) override {
-    for (const auto& attr : el->attributes) {
-      EXPECT_EQ(std::string(), attr.namespace_uri);
-    }
-    EXPECT_EQ(std::string(), el->namespace_uri);
-    xml::Visitor::Visit(el);
-  }
+    EXPECT_THAT(el->namespace_decls, SizeIs(0u));
 
-  void Visit(xml::Namespace* ns) override {
-    EXPECT_EQ(std::string(), ns->namespace_uri);
-    xml::Visitor::Visit(ns);
+    for (const auto& attr : el->attributes) {
+      EXPECT_THAT(attr.namespace_uri, StrEq(""));
+    }
+    EXPECT_THAT(el->namespace_uri, StrEq(""));
+
+    xml::Visitor::Visit(el);
   }
 
  private:
@@ -45,10 +47,9 @@
  public:
   XmlNamespaceTestVisitor() = default;
 
-  void Visit(xml::Namespace* ns) override {
-    ADD_FAILURE() << "Detected namespace: " << ns->namespace_prefix << "=\""
-                  << ns->namespace_uri << "\"";
-    xml::Visitor::Visit(ns);
+  void Visit(xml::Element* el) override {
+    EXPECT_THAT(el->namespace_decls, SizeIs(0u));
+    xml::Visitor::Visit(el);
   }
 
  private:
@@ -58,8 +59,7 @@
 class XmlNamespaceRemoverTest : public ::testing::Test {
  public:
   void SetUp() override {
-    context_ =
-        test::ContextBuilder().SetCompilationPackage("com.app.test").Build();
+    context_ = test::ContextBuilder().SetCompilationPackage("com.app.test").Build();
   }
 
  protected:
@@ -75,8 +75,8 @@
   XmlNamespaceRemover remover;
   ASSERT_TRUE(remover.Consume(context_.get(), doc.get()));
 
-  xml::Node* root = doc.get()->root.get();
-  ASSERT_NE(root, nullptr);
+  xml::Node* root = doc->root.get();
+  ASSERT_THAT(root, NotNull());
 
   XmlUriTestVisitor visitor;
   root->Accept(&visitor);
@@ -93,8 +93,8 @@
   XmlNamespaceRemover remover;
   ASSERT_TRUE(remover.Consume(context_.get(), doc.get()));
 
-  xml::Node* root = doc.get()->root.get();
-  ASSERT_NE(root, nullptr);
+  xml::Node* root = doc->root.get();
+  ASSERT_THAT(root, NotNull());
 
   XmlNamespaceTestVisitor visitor;
   root->Accept(&visitor);
@@ -112,8 +112,8 @@
   XmlNamespaceRemover remover;
   ASSERT_TRUE(remover.Consume(context_.get(), doc.get()));
 
-  xml::Node* root = doc.get()->root.get();
-  ASSERT_NE(root, nullptr);
+  xml::Node* root = doc->root.get();
+  ASSERT_THAT(root, NotNull());
 
   XmlNamespaceTestVisitor visitor;
   root->Accept(&visitor);
diff --git a/tools/aapt2/link/XmlReferenceLinker.cpp b/tools/aapt2/link/XmlReferenceLinker.cpp
index 721fc26..bcecd20 100644
--- a/tools/aapt2/link/XmlReferenceLinker.cpp
+++ b/tools/aapt2/link/XmlReferenceLinker.cpp
@@ -144,7 +144,9 @@
     xml::PackageAwareVisitor::Visit(el);
   }
 
-  bool HasError() { return error_ || reference_visitor_.HasError(); }
+  bool HasError() {
+    return error_ || reference_visitor_.HasError();
+  }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(XmlVisitor);
diff --git a/tools/aapt2/link/XmlReferenceLinker_test.cpp b/tools/aapt2/link/XmlReferenceLinker_test.cpp
index 228cfb9..ef99355 100644
--- a/tools/aapt2/link/XmlReferenceLinker_test.cpp
+++ b/tools/aapt2/link/XmlReferenceLinker_test.cpp
@@ -79,20 +79,20 @@
 };
 
 TEST_F(XmlReferenceLinkerTest, LinkBasicAttributes) {
-  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF(
-        <View xmlns:android="http://schemas.android.com/apk/res/android"
-              android:layout_width="match_parent"
-              android:background="@color/green"
-              android:text="hello"
-              android:attr="\?hello"
-              nonAaptAttr="1"
-              nonAaptAttrRef="@id/id"
-              class="hello" />)EOF");
+  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"(
+      <View xmlns:android="http://schemas.android.com/apk/res/android"
+            android:layout_width="match_parent"
+            android:background="@color/green"
+            android:text="hello"
+            android:attr="\?hello"
+            nonAaptAttr="1"
+            nonAaptAttrRef="@id/id"
+            class="hello" />)");
 
   XmlReferenceLinker linker;
   ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
 
-  xml::Element* view_el = xml::FindRootElement(doc.get());
+  xml::Element* view_el = doc->root.get();
   ASSERT_THAT(view_el, NotNull());
 
   xml::Attribute* xml_attr = view_el->FindAttribute(xml::kSchemaAndroid, "layout_width");
@@ -138,32 +138,32 @@
 }
 
 TEST_F(XmlReferenceLinkerTest, PrivateSymbolsAreNotLinked) {
-  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF(
-        <View xmlns:android="http://schemas.android.com/apk/res/android"
-              android:colorAccent="@android:color/hidden" />)EOF");
+  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"(
+      <View xmlns:android="http://schemas.android.com/apk/res/android"
+          android:colorAccent="@android:color/hidden" />)");
 
   XmlReferenceLinker linker;
   ASSERT_FALSE(linker.Consume(context_.get(), doc.get()));
 }
 
 TEST_F(XmlReferenceLinkerTest, PrivateSymbolsAreLinkedWhenReferenceHasStarPrefix) {
-  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF(
+  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"(
     <View xmlns:android="http://schemas.android.com/apk/res/android"
-          android:colorAccent="@*android:color/hidden" />)EOF");
+          android:colorAccent="@*android:color/hidden" />)");
 
   XmlReferenceLinker linker;
   ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
 }
 
 TEST_F(XmlReferenceLinkerTest, LinkMangledAttributes) {
-  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF(
-            <View xmlns:support="http://schemas.android.com/apk/res/com.android.support"
-                  support:colorAccent="#ff0000" />)EOF");
+  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"(
+      <View xmlns:support="http://schemas.android.com/apk/res/com.android.support"
+          support:colorAccent="#ff0000" />)");
 
   XmlReferenceLinker linker;
   ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
 
-  xml::Element* view_el = xml::FindRootElement(doc.get());
+  xml::Element* view_el = doc->root.get();
   ASSERT_THAT(view_el, NotNull());
 
   xml::Attribute* xml_attr =
@@ -175,14 +175,14 @@
 }
 
 TEST_F(XmlReferenceLinkerTest, LinkAutoResReference) {
-  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF(
-            <View xmlns:app="http://schemas.android.com/apk/res-auto"
-                  app:colorAccent="@app:color/red" />)EOF");
+  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"(
+      <View xmlns:app="http://schemas.android.com/apk/res-auto"
+          app:colorAccent="@app:color/red" />)");
 
   XmlReferenceLinker linker;
   ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
 
-  xml::Element* view_el = xml::FindRootElement(doc.get());
+  xml::Element* view_el = doc->root.get();
   ASSERT_THAT(view_el, NotNull());
 
   xml::Attribute* xml_attr = view_el->FindAttribute(xml::kSchemaAuto, "colorAccent");
@@ -196,17 +196,15 @@
 }
 
 TEST_F(XmlReferenceLinkerTest, LinkViewWithShadowedPackageAlias) {
-  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF(
-            <View xmlns:app="http://schemas.android.com/apk/res/android"
-                  app:attr="@app:id/id">
-              <View xmlns:app="http://schemas.android.com/apk/res/com.app.test"
-                    app:attr="@app:id/id"/>
-            </View>)EOF");
+  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"(
+      <View xmlns:app="http://schemas.android.com/apk/res/android" app:attr="@app:id/id">
+        <View xmlns:app="http://schemas.android.com/apk/res/com.app.test" app:attr="@app:id/id"/>
+      </View>)");
 
   XmlReferenceLinker linker;
   ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
 
-  xml::Element* view_el = xml::FindRootElement(doc.get());
+  xml::Element* view_el = doc->root.get();
   ASSERT_THAT(view_el, NotNull());
 
   // All attributes and references in this element should be referring to
@@ -235,14 +233,14 @@
 }
 
 TEST_F(XmlReferenceLinkerTest, LinkViewWithLocalPackageAndAliasOfTheSameName) {
-  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF(
-            <View xmlns:android="http://schemas.android.com/apk/res/com.app.test"
-                  android:attr="@id/id"/>)EOF");
+  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"(
+      <View xmlns:android="http://schemas.android.com/apk/res/com.app.test"
+          android:attr="@id/id"/>)");
 
   XmlReferenceLinker linker;
   ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
 
-  xml::Element* view_el = xml::FindRootElement(doc.get());
+  xml::Element* view_el = doc->root.get();
   ASSERT_THAT(view_el, NotNull());
 
   // All attributes and references in this element should be referring to
diff --git a/tools/aapt2/proto/ProtoHelpers.cpp b/tools/aapt2/proto/ProtoHelpers.cpp
index 6b21364..aa99c98 100644
--- a/tools/aapt2/proto/ProtoHelpers.cpp
+++ b/tools/aapt2/proto/ProtoHelpers.cpp
@@ -36,7 +36,7 @@
   StringPool::Ref ref = src_pool->MakeRef(source.path);
   out_pb_source->set_path_idx(static_cast<uint32_t>(ref.index()));
   if (source.line) {
-    out_pb_source->set_line_no(static_cast<uint32_t>(source.line.value()));
+    out_pb_source->mutable_position()->set_line_number(static_cast<uint32_t>(source.line.value()));
   }
 }
 
@@ -46,29 +46,28 @@
     out_source->path = util::GetString(src_pool, pb_source.path_idx());
   }
 
-  if (pb_source.has_line_no()) {
-    out_source->line = static_cast<size_t>(pb_source.line_no());
+  if (pb_source.has_position()) {
+    out_source->line = static_cast<size_t>(pb_source.position().line_number());
   }
 }
 
 pb::SymbolStatus_Visibility SerializeVisibilityToPb(SymbolState state) {
   switch (state) {
     case SymbolState::kPrivate:
-      return pb::SymbolStatus_Visibility_Private;
+      return pb::SymbolStatus_Visibility_PRIVATE;
     case SymbolState::kPublic:
-      return pb::SymbolStatus_Visibility_Public;
+      return pb::SymbolStatus_Visibility_PUBLIC;
     default:
       break;
   }
-  return pb::SymbolStatus_Visibility_Unknown;
+  return pb::SymbolStatus_Visibility_UNKNOWN;
 }
 
-SymbolState DeserializeVisibilityFromPb(
-    pb::SymbolStatus_Visibility pb_visibility) {
+SymbolState DeserializeVisibilityFromPb(pb::SymbolStatus_Visibility pb_visibility) {
   switch (pb_visibility) {
-    case pb::SymbolStatus_Visibility_Private:
+    case pb::SymbolStatus_Visibility_PRIVATE:
       return SymbolState::kPrivate;
-    case pb::SymbolStatus_Visibility_Public:
+    case pb::SymbolStatus_Visibility_PUBLIC:
       return SymbolState::kPublic;
     default:
       break;
@@ -102,20 +101,20 @@
 pb::Reference_Type SerializeReferenceTypeToPb(Reference::Type type) {
   switch (type) {
     case Reference::Type::kResource:
-      return pb::Reference_Type_Ref;
+      return pb::Reference_Type_REFERENCE;
     case Reference::Type::kAttribute:
-      return pb::Reference_Type_Attr;
+      return pb::Reference_Type_ATTRIBUTE;
     default:
       break;
   }
-  return pb::Reference_Type_Ref;
+  return pb::Reference_Type_REFERENCE;
 }
 
 Reference::Type DeserializeReferenceTypeFromPb(pb::Reference_Type pb_type) {
   switch (pb_type) {
-    case pb::Reference_Type_Ref:
+    case pb::Reference_Type_REFERENCE:
       return Reference::Type::kResource;
-    case pb::Reference_Type_Attr:
+    case pb::Reference_Type_ATTRIBUTE:
       return Reference::Type::kAttribute;
     default:
       break;
@@ -126,32 +125,32 @@
 pb::Plural_Arity SerializePluralEnumToPb(size_t plural_idx) {
   switch (plural_idx) {
     case Plural::Zero:
-      return pb::Plural_Arity_Zero;
+      return pb::Plural_Arity_ZERO;
     case Plural::One:
-      return pb::Plural_Arity_One;
+      return pb::Plural_Arity_ONE;
     case Plural::Two:
-      return pb::Plural_Arity_Two;
+      return pb::Plural_Arity_TWO;
     case Plural::Few:
-      return pb::Plural_Arity_Few;
+      return pb::Plural_Arity_FEW;
     case Plural::Many:
-      return pb::Plural_Arity_Many;
+      return pb::Plural_Arity_MANY;
     default:
       break;
   }
-  return pb::Plural_Arity_Other;
+  return pb::Plural_Arity_OTHER;
 }
 
 size_t DeserializePluralEnumFromPb(pb::Plural_Arity arity) {
   switch (arity) {
-    case pb::Plural_Arity_Zero:
+    case pb::Plural_Arity_ZERO:
       return Plural::Zero;
-    case pb::Plural_Arity_One:
+    case pb::Plural_Arity_ONE:
       return Plural::One;
-    case pb::Plural_Arity_Two:
+    case pb::Plural_Arity_TWO:
       return Plural::Two;
-    case pb::Plural_Arity_Few:
+    case pb::Plural_Arity_FEW:
       return Plural::Few;
-    case pb::Plural_Arity_Many:
+    case pb::Plural_Arity_MANY:
       return Plural::Many;
     default:
       break;
diff --git a/tools/aapt2/proto/ProtoHelpers.h b/tools/aapt2/proto/ProtoHelpers.h
index 344e947..2f268f4 100644
--- a/tools/aapt2/proto/ProtoHelpers.h
+++ b/tools/aapt2/proto/ProtoHelpers.h
@@ -23,27 +23,23 @@
 #include "ResourceTable.h"
 #include "Source.h"
 #include "StringPool.h"
-#include "Format.pb.h"
+#include "Resources.pb.h"
+#include "ResourcesInternal.pb.h"
 
 namespace aapt {
 
-void SerializeStringPoolToPb(const StringPool& pool,
-                             pb::StringPool* out_pb_pool);
+void SerializeStringPoolToPb(const StringPool& pool, pb::StringPool* out_pb_pool);
 
-void SerializeSourceToPb(const Source& source, StringPool* src_pool,
-                         pb::Source* out_pb_source);
+void SerializeSourceToPb(const Source& source, StringPool* src_pool, pb::Source* out_pb_source);
 
-void DeserializeSourceFromPb(const pb::Source& pb_source,
-                             const android::ResStringPool& src_pool,
+void DeserializeSourceFromPb(const pb::Source& pb_source, const android::ResStringPool& src_pool,
                              Source* out_source);
 
 pb::SymbolStatus_Visibility SerializeVisibilityToPb(SymbolState state);
 
-SymbolState DeserializeVisibilityFromPb(
-    pb::SymbolStatus_Visibility pb_visibility);
+SymbolState DeserializeVisibilityFromPb(pb::SymbolStatus_Visibility pb_visibility);
 
-void SerializeConfig(const ConfigDescription& config,
-                     pb::ConfigDescription* out_pb_config);
+void SerializeConfig(const ConfigDescription& config, pb::ConfigDescription* out_pb_config);
 
 bool DeserializeConfigDescriptionFromPb(const pb::ConfigDescription& pb_config,
                                         ConfigDescription* out_config);
diff --git a/tools/aapt2/proto/ProtoSerialize.h b/tools/aapt2/proto/ProtoSerialize.h
index 39c5003..8c46642 100644
--- a/tools/aapt2/proto/ProtoSerialize.h
+++ b/tools/aapt2/proto/ProtoSerialize.h
@@ -30,11 +30,10 @@
 
 class CompiledFileOutputStream {
  public:
-  explicit CompiledFileOutputStream(
-      google::protobuf::io::ZeroCopyOutputStream* out);
+  explicit CompiledFileOutputStream(google::protobuf::io::ZeroCopyOutputStream* out);
 
   void WriteLittleEndian32(uint32_t value);
-  void WriteCompiledFile(const pb::CompiledFile* compiledFile);
+  void WriteCompiledFile(const pb::internal::CompiledFile* compiledFile);
   void WriteData(const BigBuffer* buffer);
   void WriteData(const void* data, size_t len);
   bool HadError();
@@ -52,7 +51,7 @@
   explicit CompiledFileInputStream(const void* data, size_t size);
 
   bool ReadLittleEndian32(uint32_t* outVal);
-  bool ReadCompiledFile(pb::CompiledFile* outVal);
+  bool ReadCompiledFile(pb::internal::CompiledFile* outVal);
   bool ReadDataMetaData(uint64_t* outOffset, uint64_t* outLen);
 
  private:
@@ -64,13 +63,12 @@
 };
 
 std::unique_ptr<pb::ResourceTable> SerializeTableToPb(ResourceTable* table);
-std::unique_ptr<ResourceTable> DeserializeTableFromPb(
-    const pb::ResourceTable& pbTable, const Source& source, IDiagnostics* diag);
+std::unique_ptr<ResourceTable> DeserializeTableFromPb(const pb::ResourceTable& pbTable,
+                                                      const Source& source, IDiagnostics* diag);
 
-std::unique_ptr<pb::CompiledFile> SerializeCompiledFileToPb(
-    const ResourceFile& file);
+std::unique_ptr<pb::internal::CompiledFile> SerializeCompiledFileToPb(const ResourceFile& file);
 std::unique_ptr<ResourceFile> DeserializeCompiledFileFromPb(
-    const pb::CompiledFile& pbFile, const Source& source, IDiagnostics* diag);
+    const pb::internal::CompiledFile& pbFile, const Source& source, IDiagnostics* diag);
 
 }  // namespace aapt
 
diff --git a/tools/aapt2/proto/TableProtoDeserializer.cpp b/tools/aapt2/proto/TableProtoDeserializer.cpp
index 37d5ed0..b9d5878 100644
--- a/tools/aapt2/proto/TableProtoDeserializer.cpp
+++ b/tools/aapt2/proto/TableProtoDeserializer.cpp
@@ -55,66 +55,61 @@
 
 class PackagePbDeserializer {
  public:
-  PackagePbDeserializer(const android::ResStringPool* valuePool,
-                        const android::ResStringPool* sourcePool,
-                        const android::ResStringPool* symbolPool,
-                        const Source& source, IDiagnostics* diag)
-      : value_pool_(valuePool),
-        source_pool_(sourcePool),
-        symbol_pool_(symbolPool),
-        source_(source),
-        diag_(diag) {}
+  PackagePbDeserializer(const android::ResStringPool* sourcePool, const Source& source,
+                        IDiagnostics* diag)
+      : source_pool_(sourcePool), source_(source), diag_(diag) {
+  }
 
  public:
-  bool DeserializeFromPb(const pb::Package& pbPackage, ResourceTable* table) {
+  bool DeserializeFromPb(const pb::Package& pb_package, ResourceTable* table) {
     Maybe<uint8_t> id;
-    if (pbPackage.has_package_id()) {
-      id = static_cast<uint8_t>(pbPackage.package_id());
+    if (pb_package.has_package_id()) {
+      id = static_cast<uint8_t>(pb_package.package_id());
     }
 
-    std::map<ResourceId, ResourceNameRef> idIndex;
+    std::map<ResourceId, ResourceNameRef> id_index;
 
-    ResourceTablePackage* pkg = table->CreatePackage(pbPackage.package_name(), id);
-    for (const pb::Type& pbType : pbPackage.types()) {
-      const ResourceType* resType = ParseResourceType(pbType.name());
-      if (!resType) {
-        diag_->Error(DiagMessage(source_) << "unknown type '" << pbType.name() << "'");
+    ResourceTablePackage* pkg = table->CreatePackage(pb_package.package_name(), id);
+    for (const pb::Type& pb_type : pb_package.type()) {
+      const ResourceType* res_type = ParseResourceType(pb_type.name());
+      if (res_type == nullptr) {
+        diag_->Error(DiagMessage(source_) << "unknown type '" << pb_type.name() << "'");
         return {};
       }
 
-      ResourceTableType* type = pkg->FindOrCreateType(*resType);
+      ResourceTableType* type = pkg->FindOrCreateType(*res_type);
 
-      for (const pb::Entry& pbEntry : pbType.entries()) {
-        ResourceEntry* entry = type->FindOrCreateEntry(pbEntry.name());
+      for (const pb::Entry& pb_entry : pb_type.entry()) {
+        ResourceEntry* entry = type->FindOrCreateEntry(pb_entry.name());
 
-        // Deserialize the symbol status (public/private with source and
-        // comments).
-        if (pbEntry.has_symbol_status()) {
-          const pb::SymbolStatus& pbStatus = pbEntry.symbol_status();
-          if (pbStatus.has_source()) {
-            DeserializeSourceFromPb(pbStatus.source(), *source_pool_, &entry->symbol_status.source);
+        // Deserialize the symbol status (public/private with source and comments).
+        if (pb_entry.has_symbol_status()) {
+          const pb::SymbolStatus& pb_status = pb_entry.symbol_status();
+          if (pb_status.has_source()) {
+            DeserializeSourceFromPb(pb_status.source(), *source_pool_,
+                                    &entry->symbol_status.source);
           }
 
-          if (pbStatus.has_comment()) {
-            entry->symbol_status.comment = pbStatus.comment();
+          if (pb_status.has_comment()) {
+            entry->symbol_status.comment = pb_status.comment();
           }
 
-          entry->symbol_status.allow_new = pbStatus.allow_new();
+          entry->symbol_status.allow_new = pb_status.allow_new();
 
-          SymbolState visibility = DeserializeVisibilityFromPb(pbStatus.visibility());
+          SymbolState visibility = DeserializeVisibilityFromPb(pb_status.visibility());
           entry->symbol_status.state = visibility;
 
           if (visibility == SymbolState::kPublic) {
             // This is a public symbol, we must encode the ID now if there is one.
-            if (pbEntry.has_id()) {
-              entry->id = static_cast<uint16_t>(pbEntry.id());
+            if (pb_entry.has_id()) {
+              entry->id = static_cast<uint16_t>(pb_entry.id());
             }
 
             if (type->symbol_status.state != SymbolState::kPublic) {
               // If the type has not been made public, do so now.
               type->symbol_status.state = SymbolState::kPublic;
-              if (pbType.has_id()) {
-                type->id = static_cast<uint8_t>(pbType.id());
+              if (pb_type.has_id()) {
+                type->id = static_cast<uint8_t>(pb_type.id());
               }
             }
           } else if (visibility == SymbolState::kPrivate) {
@@ -124,45 +119,44 @@
           }
         }
 
-        ResourceId resId(pbPackage.package_id(), pbType.id(), pbEntry.id());
-        if (resId.is_valid()) {
-          idIndex[resId] = ResourceNameRef(pkg->name, type->type, entry->name);
+        ResourceId resid(pb_package.package_id(), pb_type.id(), pb_entry.id());
+        if (resid.is_valid()) {
+          id_index[resid] = ResourceNameRef(pkg->name, type->type, entry->name);
         }
 
-        for (const pb::ConfigValue& pbConfigValue : pbEntry.config_values()) {
-          const pb::ConfigDescription& pbConfig = pbConfigValue.config();
+        for (const pb::ConfigValue& pb_config_value : pb_entry.config_value()) {
+          const pb::ConfigDescription& pb_config = pb_config_value.config();
 
           ConfigDescription config;
-          if (!DeserializeConfigDescriptionFromPb(pbConfig, &config)) {
+          if (!DeserializeConfigDescriptionFromPb(pb_config, &config)) {
             diag_->Error(DiagMessage(source_) << "invalid configuration");
             return {};
           }
 
-          ResourceConfigValue* configValue = entry->FindOrCreateValue(config, pbConfig.product());
-          if (configValue->value) {
+          ResourceConfigValue* config_value = entry->FindOrCreateValue(config, pb_config.product());
+          if (config_value->value) {
             // Duplicate config.
             diag_->Error(DiagMessage(source_) << "duplicate configuration");
             return {};
           }
 
-          configValue->value =
-              DeserializeValueFromPb(pbConfigValue.value(), config, &table->string_pool);
-          if (!configValue->value) {
+          config_value->value =
+              DeserializeValueFromPb(pb_config_value.value(), config, &table->string_pool);
+          if (!config_value->value) {
             return {};
           }
         }
       }
     }
 
-    ReferenceIdToNameVisitor visitor(&idIndex);
+    ReferenceIdToNameVisitor visitor(&id_index);
     VisitAllValuesInPackage(pkg, &visitor);
     return true;
   }
 
  private:
   std::unique_ptr<Item> DeserializeItemFromPb(const pb::Item& pb_item,
-                                              const ConfigDescription& config,
-                                              StringPool* pool) {
+                                              const ConfigDescription& config, StringPool* pool) {
     if (pb_item.has_ref()) {
       const pb::Reference& pb_ref = pb_item.ref();
       std::unique_ptr<Reference> ref = util::make_unique<Reference>();
@@ -173,45 +167,32 @@
 
     } else if (pb_item.has_prim()) {
       const pb::Primitive& pb_prim = pb_item.prim();
-      android::Res_value prim = {};
-      prim.dataType = static_cast<uint8_t>(pb_prim.type());
-      prim.data = pb_prim.data();
-      return util::make_unique<BinaryPrimitive>(prim);
+      return util::make_unique<BinaryPrimitive>(static_cast<uint8_t>(pb_prim.type()),
+                                                pb_prim.data());
 
     } else if (pb_item.has_id()) {
       return util::make_unique<Id>();
 
     } else if (pb_item.has_str()) {
-      const uint32_t idx = pb_item.str().idx();
-      const std::string str = util::GetString(*value_pool_, idx);
-
-      const android::ResStringPool_span* spans = value_pool_->styleAt(idx);
-      if (spans && spans->name.index != android::ResStringPool_span::END) {
-        StyleString style_str = {str};
-        while (spans->name.index != android::ResStringPool_span::END) {
-          style_str.spans.push_back(
-              Span{util::GetString(*value_pool_, spans->name.index),
-                   spans->firstChar, spans->lastChar});
-          spans++;
-        }
-        return util::make_unique<StyledString>(pool->MakeRef(
-            style_str, StringPool::Context(StringPool::Context::kNormalPriority, config)));
-      }
       return util::make_unique<String>(
-          pool->MakeRef(str, StringPool::Context(config)));
+          pool->MakeRef(pb_item.str().value(), StringPool::Context(config)));
 
     } else if (pb_item.has_raw_str()) {
-      const uint32_t idx = pb_item.raw_str().idx();
-      const std::string str = util::GetString(*value_pool_, idx);
       return util::make_unique<RawString>(
-          pool->MakeRef(str, StringPool::Context(config)));
+          pool->MakeRef(pb_item.raw_str().value(), StringPool::Context(config)));
+
+    } else if (pb_item.has_styled_str()) {
+      const pb::StyledString& pb_str = pb_item.styled_str();
+      StyleString style_str{pb_str.value()};
+      for (const pb::StyledString::Span& pb_span : pb_str.span()) {
+        style_str.spans.push_back(Span{pb_span.tag(), pb_span.first_char(), pb_span.last_char()});
+      }
+      return util::make_unique<StyledString>(pool->MakeRef(
+          style_str, StringPool::Context(StringPool::Context::kNormalPriority, config)));
 
     } else if (pb_item.has_file()) {
-      const uint32_t idx = pb_item.file().path_idx();
-      const std::string str = util::GetString(*value_pool_, idx);
       return util::make_unique<FileReference>(pool->MakeRef(
-          str,
-          StringPool::Context(StringPool::Context::kHighPriority, config)));
+          pb_item.file().path(), StringPool::Context(StringPool::Context::kHighPriority, config)));
 
     } else {
       diag_->Error(DiagMessage(source_) << "unknown item");
@@ -222,8 +203,6 @@
   std::unique_ptr<Value> DeserializeValueFromPb(const pb::Value& pb_value,
                                                 const ConfigDescription& config,
                                                 StringPool* pool) {
-    const bool is_weak = pb_value.has_weak() ? pb_value.weak() : false;
-
     std::unique_ptr<Value> value;
     if (pb_value.has_item()) {
       value = DeserializeItemFromPb(pb_value.item(), config, pool);
@@ -235,11 +214,11 @@
       const pb::CompoundValue& pb_compound_value = pb_value.compound_value();
       if (pb_compound_value.has_attr()) {
         const pb::Attribute& pb_attr = pb_compound_value.attr();
-        std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(is_weak);
+        std::unique_ptr<Attribute> attr = util::make_unique<Attribute>();
         attr->type_mask = pb_attr.format_flags();
         attr->min_int = pb_attr.min_int();
         attr->max_int = pb_attr.max_int();
-        for (const pb::Attribute_Symbol& pb_symbol : pb_attr.symbols()) {
+        for (const pb::Attribute_Symbol& pb_symbol : pb_attr.symbol()) {
           Attribute::Symbol symbol;
           DeserializeItemCommon(pb_symbol, &symbol.symbol);
           if (!DeserializeReferenceFromPb(pb_symbol.name(), &symbol.symbol)) {
@@ -255,20 +234,18 @@
         std::unique_ptr<Style> style = util::make_unique<Style>();
         if (pb_style.has_parent()) {
           style->parent = Reference();
-          if (!DeserializeReferenceFromPb(pb_style.parent(),
-                                          &style->parent.value())) {
+          if (!DeserializeReferenceFromPb(pb_style.parent(), &style->parent.value())) {
             return {};
           }
 
           if (pb_style.has_parent_source()) {
             Source parent_source;
-            DeserializeSourceFromPb(pb_style.parent_source(), *source_pool_,
-                                    &parent_source);
+            DeserializeSourceFromPb(pb_style.parent_source(), *source_pool_, &parent_source);
             style->parent.value().SetSource(std::move(parent_source));
           }
         }
 
-        for (const pb::Style_Entry& pb_entry : pb_style.entries()) {
+        for (const pb::Style_Entry& pb_entry : pb_style.entry()) {
           Style::Entry entry;
           DeserializeItemCommon(pb_entry, &entry.key);
           if (!DeserializeReferenceFromPb(pb_entry.key(), &entry.key)) {
@@ -288,7 +265,7 @@
       } else if (pb_compound_value.has_styleable()) {
         const pb::Styleable& pb_styleable = pb_compound_value.styleable();
         std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
-        for (const pb::Styleable_Entry& pb_entry : pb_styleable.entries()) {
+        for (const pb::Styleable_Entry& pb_entry : pb_styleable.entry()) {
           Reference attr_ref;
           DeserializeItemCommon(pb_entry, &attr_ref);
           DeserializeReferenceFromPb(pb_entry.attr(), &attr_ref);
@@ -299,25 +276,23 @@
       } else if (pb_compound_value.has_array()) {
         const pb::Array& pb_array = pb_compound_value.array();
         std::unique_ptr<Array> array = util::make_unique<Array>();
-        for (const pb::Array_Entry& pb_entry : pb_array.entries()) {
-          std::unique_ptr<Item> item =
-              DeserializeItemFromPb(pb_entry.item(), config, pool);
+        for (const pb::Array_Element& pb_entry : pb_array.element()) {
+          std::unique_ptr<Item> item = DeserializeItemFromPb(pb_entry.item(), config, pool);
           if (!item) {
             return {};
           }
 
           DeserializeItemCommon(pb_entry, item.get());
-          array->items.push_back(std::move(item));
+          array->elements.push_back(std::move(item));
         }
         value = std::move(array);
 
       } else if (pb_compound_value.has_plural()) {
         const pb::Plural& pb_plural = pb_compound_value.plural();
         std::unique_ptr<Plural> plural = util::make_unique<Plural>();
-        for (const pb::Plural_Entry& pb_entry : pb_plural.entries()) {
+        for (const pb::Plural_Entry& pb_entry : pb_plural.entry()) {
           size_t pluralIdx = DeserializePluralEnumFromPb(pb_entry.arity());
-          plural->values[pluralIdx] =
-              DeserializeItemFromPb(pb_entry.item(), config, pool);
+          plural->values[pluralIdx] = DeserializeItemFromPb(pb_entry.item(), config, pool);
           if (!plural->values[pluralIdx]) {
             return {};
           }
@@ -337,7 +312,7 @@
 
     CHECK(value) << "forgot to set value";
 
-    value->SetWeak(is_weak);
+    value->SetWeak(pb_value.weak());
     DeserializeItemCommon(pb_value, value.get());
     return value;
   }
@@ -350,11 +325,10 @@
       out_ref->id = ResourceId(pb_ref.id());
     }
 
-    if (pb_ref.has_symbol_idx()) {
-      const std::string str_symbol = util::GetString(*symbol_pool_, pb_ref.symbol_idx());
+    if (pb_ref.has_name()) {
       ResourceNameRef name_ref;
-      if (!ResourceUtils::ParseResourceName(str_symbol, &name_ref, nullptr)) {
-        diag_->Error(DiagMessage(source_) << "invalid reference name '" << str_symbol << "'");
+      if (!ResourceUtils::ParseResourceName(pb_ref.name(), &name_ref, nullptr)) {
+        diag_->Error(DiagMessage(source_) << "invalid reference name '" << pb_ref.name() << "'");
         return false;
       }
 
@@ -377,61 +351,33 @@
   }
 
  private:
-  const android::ResStringPool* value_pool_;
   const android::ResStringPool* source_pool_;
-  const android::ResStringPool* symbol_pool_;
   const Source source_;
   IDiagnostics* diag_;
 };
 
 }  // namespace
 
-std::unique_ptr<ResourceTable> DeserializeTableFromPb(
-    const pb::ResourceTable& pb_table, const Source& source,
-    IDiagnostics* diag) {
-  // We import the android namespace because on Windows NO_ERROR is a macro, not
-  // an enum, which
+std::unique_ptr<ResourceTable> DeserializeTableFromPb(const pb::ResourceTable& pb_table,
+                                                      const Source& source, IDiagnostics* diag) {
+  // We import the android namespace because on Windows NO_ERROR is a macro, not an enum, which
   // causes errors when qualifying it with android::
   using namespace android;
 
   std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
 
-  if (!pb_table.has_string_pool()) {
-    diag->Error(DiagMessage(source) << "no string pool found");
-    return {};
-  }
-
-  ResStringPool value_pool;
-  status_t result = value_pool.setTo(pb_table.string_pool().data().data(),
-                                     pb_table.string_pool().data().size());
-  if (result != NO_ERROR) {
-    diag->Error(DiagMessage(source) << "invalid string pool");
-    return {};
-  }
-
   ResStringPool source_pool;
   if (pb_table.has_source_pool()) {
-    result = source_pool.setTo(pb_table.source_pool().data().data(),
-                               pb_table.source_pool().data().size());
+    status_t result = source_pool.setTo(pb_table.source_pool().data().data(),
+                                        pb_table.source_pool().data().size());
     if (result != NO_ERROR) {
       diag->Error(DiagMessage(source) << "invalid source pool");
       return {};
     }
   }
 
-  ResStringPool symbol_pool;
-  if (pb_table.has_symbol_pool()) {
-    result = symbol_pool.setTo(pb_table.symbol_pool().data().data(),
-                               pb_table.symbol_pool().data().size());
-    if (result != NO_ERROR) {
-      diag->Error(DiagMessage(source) << "invalid symbol pool");
-      return {};
-    }
-  }
-
-  PackagePbDeserializer package_pb_deserializer(&value_pool, &source_pool,
-                                                &symbol_pool, source, diag);
-  for (const pb::Package& pb_package : pb_table.packages()) {
+  PackagePbDeserializer package_pb_deserializer(&source_pool, source, diag);
+  for (const pb::Package& pb_package : pb_table.package()) {
     if (!package_pb_deserializer.DeserializeFromPb(pb_package, table.get())) {
       return {};
     }
@@ -440,7 +386,7 @@
 }
 
 std::unique_ptr<ResourceFile> DeserializeCompiledFileFromPb(
-    const pb::CompiledFile& pb_file, const Source& source, IDiagnostics* diag) {
+    const pb::internal::CompiledFile& pb_file, const Source& source, IDiagnostics* diag) {
   std::unique_ptr<ResourceFile> file = util::make_unique<ResourceFile>();
 
   ResourceNameRef name_ref;
@@ -456,19 +402,20 @@
   file->source.path = pb_file.source_path();
   DeserializeConfigDescriptionFromPb(pb_file.config(), &file->config);
 
-  for (const pb::CompiledFile_Symbol& pb_symbol : pb_file.exported_symbols()) {
-    // Need to create an lvalue here so that nameRef can point to something
-    // real.
-    if (!ResourceUtils::ParseResourceName(pb_symbol.resource_name(),
-                                          &name_ref)) {
+  for (const pb::internal::CompiledFile_Symbol& pb_symbol : pb_file.exported_symbol()) {
+    // Need to create an lvalue here so that nameRef can point to something real.
+    if (!ResourceUtils::ParseResourceName(pb_symbol.resource_name(), &name_ref)) {
       diag->Error(DiagMessage(source)
                   << "invalid resource name for exported symbol in "
                      "compiled file header: "
                   << pb_file.resource_name());
       return {};
     }
-    file->exported_symbols.push_back(
-        SourcedResourceName{name_ref.ToResourceName(), pb_symbol.line_no()});
+    size_t line = 0u;
+    if (pb_symbol.has_source()) {
+      line = pb_symbol.source().line_number();
+    }
+    file->exported_symbols.push_back(SourcedResourceName{name_ref.ToResourceName(), line});
   }
   return file;
 }
diff --git a/tools/aapt2/proto/TableProtoSerializer.cpp b/tools/aapt2/proto/TableProtoSerializer.cpp
index 730442c..a08df71 100644
--- a/tools/aapt2/proto/TableProtoSerializer.cpp
+++ b/tools/aapt2/proto/TableProtoSerializer.cpp
@@ -24,9 +24,9 @@
 
 #include "android-base/logging.h"
 
-using google::protobuf::io::CodedOutputStream;
-using google::protobuf::io::CodedInputStream;
-using google::protobuf::io::ZeroCopyOutputStream;
+using ::google::protobuf::io::CodedInputStream;
+using ::google::protobuf::io::CodedOutputStream;
+using ::google::protobuf::io::ZeroCopyOutputStream;
 
 namespace aapt {
 
@@ -36,46 +36,46 @@
  public:
   using RawValueVisitor::Visit;
 
-  /**
-   * Constructor to use when expecting to serialize any value.
-   */
-  PbSerializerVisitor(StringPool* source_pool, StringPool* symbol_pool,
-                      pb::Value* out_pb_value)
-      : source_pool_(source_pool),
-        symbol_pool_(symbol_pool),
-        out_pb_value_(out_pb_value),
-        out_pb_item_(nullptr) {}
+  // Constructor to use when expecting to serialize any value.
+  PbSerializerVisitor(StringPool* source_pool, pb::Value* out_pb_value)
+      : source_pool_(source_pool), out_pb_value_(out_pb_value), out_pb_item_(nullptr) {
+  }
 
-  /**
-   * Constructor to use when expecting to serialize an Item.
-   */
-  PbSerializerVisitor(StringPool* sourcePool, StringPool* symbolPool,
-                      pb::Item* outPbItem)
-      : source_pool_(sourcePool),
-        symbol_pool_(symbolPool),
-        out_pb_value_(nullptr),
-        out_pb_item_(outPbItem) {}
+  // Constructor to use when expecting to serialize an Item.
+  PbSerializerVisitor(StringPool* sourcePool, pb::Item* outPbItem)
+      : source_pool_(sourcePool), out_pb_value_(nullptr), out_pb_item_(outPbItem) {
+  }
 
   void Visit(Reference* ref) override {
     SerializeReferenceToPb(*ref, pb_item()->mutable_ref());
   }
 
   void Visit(String* str) override {
-    pb_item()->mutable_str()->set_idx(str->value.index());
+    pb_item()->mutable_str()->set_value(*str->value);
+  }
+
+  void Visit(RawString* str) override {
+    pb_item()->mutable_raw_str()->set_value(*str->value);
   }
 
   void Visit(StyledString* str) override {
-    pb_item()->mutable_str()->set_idx(str->value.index());
+    pb::StyledString* pb_str = pb_item()->mutable_styled_str();
+    pb_str->set_value(str->value->value);
+
+    for (const StringPool::Span& span : str->value->spans) {
+      pb::StyledString::Span* pb_span = pb_str->add_span();
+      pb_span->set_tag(*span.name);
+      pb_span->set_first_char(span.first_char);
+      pb_span->set_last_char(span.last_char);
+    }
   }
 
   void Visit(FileReference* file) override {
-    pb_item()->mutable_file()->set_path_idx(file->path.index());
+    pb_item()->mutable_file()->set_path(*file->path);
   }
 
-  void Visit(Id* id) override { pb_item()->mutable_id(); }
-
-  void Visit(RawString* raw_str) override {
-    pb_item()->mutable_raw_str()->set_idx(raw_str->value.index());
+  void Visit(Id* /*id*/) override {
+    pb_item()->mutable_id();
   }
 
   void Visit(BinaryPrimitive* prim) override {
@@ -98,7 +98,7 @@
     pb_attr->set_max_int(attr->max_int);
 
     for (auto& symbol : attr->symbols) {
-      pb::Attribute_Symbol* pb_symbol = pb_attr->add_symbols();
+      pb::Attribute_Symbol* pb_symbol = pb_attr->add_symbol();
       SerializeItemCommonToPb(symbol.symbol, pb_symbol);
       SerializeReferenceToPb(symbol.symbol, pb_symbol->mutable_name());
       pb_symbol->set_value(symbol.value);
@@ -114,12 +114,12 @@
     }
 
     for (Style::Entry& entry : style->entries) {
-      pb::Style_Entry* pb_entry = pb_style->add_entries();
+      pb::Style_Entry* pb_entry = pb_style->add_entry();
       SerializeReferenceToPb(entry.key, pb_entry->mutable_key());
 
       pb::Item* pb_item = pb_entry->mutable_item();
       SerializeItemCommonToPb(entry.key, pb_entry);
-      PbSerializerVisitor sub_visitor(source_pool_, symbol_pool_, pb_item);
+      PbSerializerVisitor sub_visitor(source_pool_, pb_item);
       entry.value->Accept(&sub_visitor);
     }
   }
@@ -127,7 +127,7 @@
   void Visit(Styleable* styleable) override {
     pb::Styleable* pb_styleable = pb_compound_value()->mutable_styleable();
     for (Reference& entry : styleable->entries) {
-      pb::Styleable_Entry* pb_entry = pb_styleable->add_entries();
+      pb::Styleable_Entry* pb_entry = pb_styleable->add_entry();
       SerializeItemCommonToPb(entry, pb_entry);
       SerializeReferenceToPb(entry, pb_entry->mutable_attr());
     }
@@ -135,11 +135,10 @@
 
   void Visit(Array* array) override {
     pb::Array* pb_array = pb_compound_value()->mutable_array();
-    for (auto& value : array->items) {
-      pb::Array_Entry* pb_entry = pb_array->add_entries();
-      SerializeItemCommonToPb(*value, pb_entry);
-      PbSerializerVisitor sub_visitor(source_pool_, symbol_pool_,
-                                      pb_entry->mutable_item());
+    for (auto& value : array->elements) {
+      pb::Array_Element* pb_element = pb_array->add_element();
+      SerializeItemCommonToPb(*value, pb_element);
+      PbSerializerVisitor sub_visitor(source_pool_, pb_element->mutable_item());
       value->Accept(&sub_visitor);
     }
   }
@@ -153,11 +152,11 @@
         continue;
       }
 
-      pb::Plural_Entry* pb_entry = pb_plural->add_entries();
+      pb::Plural_Entry* pb_entry = pb_plural->add_entry();
       pb_entry->set_arity(SerializePluralEnumToPb(i));
       pb::Item* pb_element = pb_entry->mutable_item();
       SerializeItemCommonToPb(*plural->values[i], pb_entry);
-      PbSerializerVisitor sub_visitor(source_pool_, symbol_pool_, pb_element);
+      PbSerializerVisitor sub_visitor(source_pool_, pb_element);
       plural->values[i]->Accept(&sub_visitor);
     }
   }
@@ -179,8 +178,7 @@
 
   template <typename T>
   void SerializeItemCommonToPb(const Item& item, T* pb_item) {
-    SerializeSourceToPb(item.GetSource(), source_pool_,
-                        pb_item->mutable_source());
+    SerializeSourceToPb(item.GetSource(), source_pool_, pb_item->mutable_source());
     if (!item.GetComment().empty()) {
       pb_item->set_comment(item.GetComment());
     }
@@ -192,8 +190,7 @@
     }
 
     if (ref.name) {
-      StringPool::Ref symbol_ref = symbol_pool_->MakeRef(ref.name.value().ToString());
-      pb_ref->set_symbol_idx(static_cast<uint32_t>(symbol_ref.index()));
+      pb_ref->set_name(ref.name.value().ToString());
     }
 
     pb_ref->set_private_(ref.private_reference);
@@ -201,7 +198,6 @@
   }
 
   StringPool* source_pool_;
-  StringPool* symbol_pool_;
   pb::Value* out_pb_value_;
   pb::Item* out_pb_item_;
 };
@@ -220,26 +216,24 @@
   });
 
   auto pb_table = util::make_unique<pb::ResourceTable>();
-  SerializeStringPoolToPb(table->string_pool, pb_table->mutable_string_pool());
-
-  StringPool source_pool, symbol_pool;
+  StringPool source_pool;
 
   for (auto& package : table->packages) {
-    pb::Package* pb_package = pb_table->add_packages();
+    pb::Package* pb_package = pb_table->add_package();
     if (package->id) {
       pb_package->set_package_id(package->id.value());
     }
     pb_package->set_package_name(package->name);
 
     for (auto& type : package->types) {
-      pb::Type* pb_type = pb_package->add_types();
+      pb::Type* pb_type = pb_package->add_type();
       if (type->id) {
         pb_type->set_id(type->id.value());
       }
       pb_type->set_name(ToString(type->type).to_string());
 
       for (auto& entry : type->entries) {
-        pb::Entry* pb_entry = pb_type->add_entries();
+        pb::Entry* pb_entry = pb_type->add_entry();
         if (entry->id) {
           pb_entry->set_id(entry->id.value());
         }
@@ -253,7 +247,7 @@
         pb_status->set_allow_new(entry->symbol_status.allow_new);
 
         for (auto& config_value : entry->values) {
-          pb::ConfigValue* pb_config_value = pb_entry->add_config_values();
+          pb::ConfigValue* pb_config_value = pb_entry->add_config_value();
           SerializeConfig(config_value->config, pb_config_value->mutable_config());
           if (!config_value->product.empty()) {
             pb_config_value->mutable_config()->set_product(config_value->product);
@@ -270,7 +264,7 @@
             pb_value->set_weak(true);
           }
 
-          PbSerializerVisitor visitor(&source_pool, &symbol_pool, pb_value);
+          PbSerializerVisitor visitor(&source_pool, pb_value);
           config_value->value->Accept(&visitor);
         }
       }
@@ -278,27 +272,25 @@
   }
 
   SerializeStringPoolToPb(source_pool, pb_table->mutable_source_pool());
-  SerializeStringPoolToPb(symbol_pool, pb_table->mutable_symbol_pool());
   return pb_table;
 }
 
-std::unique_ptr<pb::CompiledFile> SerializeCompiledFileToPb(
-    const ResourceFile& file) {
-  auto pb_file = util::make_unique<pb::CompiledFile>();
+std::unique_ptr<pb::internal::CompiledFile> SerializeCompiledFileToPb(const ResourceFile& file) {
+  auto pb_file = util::make_unique<pb::internal::CompiledFile>();
   pb_file->set_resource_name(file.name.ToString());
   pb_file->set_source_path(file.source.path);
   SerializeConfig(file.config, pb_file->mutable_config());
 
   for (const SourcedResourceName& exported : file.exported_symbols) {
-    pb::CompiledFile_Symbol* pb_symbol = pb_file->add_exported_symbols();
+    pb::internal::CompiledFile_Symbol* pb_symbol = pb_file->add_exported_symbol();
     pb_symbol->set_resource_name(exported.name.ToString());
-    pb_symbol->set_line_no(exported.line);
+    pb_symbol->mutable_source()->set_line_number(exported.line);
   }
   return pb_file;
 }
 
-CompiledFileOutputStream::CompiledFileOutputStream(ZeroCopyOutputStream* out)
-    : out_(out) {}
+CompiledFileOutputStream::CompiledFileOutputStream(ZeroCopyOutputStream* out) : out_(out) {
+}
 
 void CompiledFileOutputStream::EnsureAlignedWrite() {
   const int padding = out_.ByteCount() % 4;
@@ -313,8 +305,7 @@
   out_.WriteLittleEndian32(val);
 }
 
-void CompiledFileOutputStream::WriteCompiledFile(
-    const pb::CompiledFile* compiled_file) {
+void CompiledFileOutputStream::WriteCompiledFile(const pb::internal::CompiledFile* compiled_file) {
   EnsureAlignedWrite();
   out_.WriteLittleEndian64(static_cast<uint64_t>(compiled_file->ByteSize()));
   compiled_file->SerializeWithCachedSizes(&out_);
@@ -334,7 +325,9 @@
   out_.WriteRaw(data, len);
 }
 
-bool CompiledFileOutputStream::HadError() { return out_.HadError(); }
+bool CompiledFileOutputStream::HadError() {
+  return out_.HadError();
+}
 
 CompiledFileInputStream::CompiledFileInputStream(const void* data, size_t size)
     : in_(static_cast<const uint8_t*>(data), size) {}
@@ -352,7 +345,7 @@
   return in_.ReadLittleEndian32(out_val);
 }
 
-bool CompiledFileInputStream::ReadCompiledFile(pb::CompiledFile* out_val) {
+bool CompiledFileInputStream::ReadCompiledFile(pb::internal::CompiledFile* out_val) {
   EnsureAlignedRead();
 
   google::protobuf::uint64 pb_size = 0u;
@@ -379,8 +372,7 @@
   return true;
 }
 
-bool CompiledFileInputStream::ReadDataMetaData(uint64_t* out_offset,
-                                               uint64_t* out_len) {
+bool CompiledFileInputStream::ReadDataMetaData(uint64_t* out_offset, uint64_t* out_len) {
   EnsureAlignedRead();
 
   google::protobuf::uint64 pb_size = 0u;
diff --git a/tools/aapt2/proto/TableProtoSerializer_test.cpp b/tools/aapt2/proto/TableProtoSerializer_test.cpp
index 3ebb08e..80608b3 100644
--- a/tools/aapt2/proto/TableProtoSerializer_test.cpp
+++ b/tools/aapt2/proto/TableProtoSerializer_test.cpp
@@ -20,7 +20,9 @@
 #include "test/Test.h"
 
 using ::google::protobuf::io::StringOutputStream;
+using ::testing::Eq;
 using ::testing::NotNull;
+using ::testing::SizeIs;
 
 namespace aapt {
 
@@ -38,12 +40,12 @@
 
   Symbol public_symbol;
   public_symbol.state = SymbolState::kPublic;
-  ASSERT_TRUE(table->SetSymbolState(
-      test::ParseNameOrDie("com.app.a:layout/main"), ResourceId(0x7f020000),
-      public_symbol, context->GetDiagnostics()));
+  ASSERT_TRUE(table->SetSymbolState(test::ParseNameOrDie("com.app.a:layout/main"),
+                                    ResourceId(0x7f020000), public_symbol,
+                                    context->GetDiagnostics()));
 
   Id* id = test::GetValue<Id>(table.get(), "com.app.a:id/foo");
-  ASSERT_NE(nullptr, id);
+  ASSERT_THAT(id, NotNull());
 
   // Make a plural.
   std::unique_ptr<Plural> plural = util::make_unique<Plural>();
@@ -52,6 +54,15 @@
                                  ConfigDescription{}, {}, std::move(plural),
                                  context->GetDiagnostics()));
 
+  // Make a styled string.
+  StyleString style_string;
+  style_string.str = "hello";
+  style_string.spans.push_back(Span{"b", 0u, 4u});
+  ASSERT_TRUE(
+      table->AddResource(test::ParseNameOrDie("com.app.a:string/styled"), ConfigDescription{}, {},
+                         util::make_unique<StyledString>(table->string_pool.MakeRef(style_string)),
+                         context->GetDiagnostics()));
+
   // Make a resource with different products.
   ASSERT_TRUE(table->AddResource(
       test::ParseNameOrDie("com.app.a:integer/one"),
@@ -65,9 +76,8 @@
       context->GetDiagnostics()));
 
   // Make a reference with both resource name and resource ID.
-  // The reference should point to a resource outside of this table to test that
-  // both
-  // name and id get serialized.
+  // The reference should point to a resource outside of this table to test that both name and id
+  // get serialized.
   Reference expected_ref;
   expected_ref.name = test::ParseNameOrDie("android:layout/main");
   expected_ref.id = ResourceId(0x01020000);
@@ -85,36 +95,45 @@
 
   Id* new_id = test::GetValue<Id>(new_table.get(), "com.app.a:id/foo");
   ASSERT_THAT(new_id, NotNull());
-  EXPECT_EQ(id->IsWeak(), new_id->IsWeak());
+  EXPECT_THAT(new_id->IsWeak(), Eq(id->IsWeak()));
 
   Maybe<ResourceTable::SearchResult> result =
       new_table->FindResource(test::ParseNameOrDie("com.app.a:layout/main"));
   ASSERT_TRUE(result);
-  EXPECT_EQ(SymbolState::kPublic, result.value().type->symbol_status.state);
-  EXPECT_EQ(SymbolState::kPublic, result.value().entry->symbol_status.state);
+
+  EXPECT_THAT(result.value().type->symbol_status.state, Eq(SymbolState::kPublic));
+  EXPECT_THAT(result.value().entry->symbol_status.state, Eq(SymbolState::kPublic));
 
   result = new_table->FindResource(test::ParseNameOrDie("com.app.a:bool/foo"));
   ASSERT_TRUE(result);
-  EXPECT_EQ(SymbolState::kUndefined, result.value().entry->symbol_status.state);
+  EXPECT_THAT(result.value().entry->symbol_status.state, Eq(SymbolState::kUndefined));
   EXPECT_TRUE(result.value().entry->symbol_status.allow_new);
 
   // Find the product-dependent values
   BinaryPrimitive* prim = test::GetValueForConfigAndProduct<BinaryPrimitive>(
       new_table.get(), "com.app.a:integer/one", test::ParseConfigOrDie("land"), "");
   ASSERT_THAT(prim, NotNull());
-  EXPECT_EQ(123u, prim->value.data);
+  EXPECT_THAT(prim->value.data, Eq(123u));
 
   prim = test::GetValueForConfigAndProduct<BinaryPrimitive>(
       new_table.get(), "com.app.a:integer/one", test::ParseConfigOrDie("land"), "tablet");
   ASSERT_THAT(prim, NotNull());
-  EXPECT_EQ(321u, prim->value.data);
+  EXPECT_THAT(prim->value.data, Eq(321u));
 
   Reference* actual_ref = test::GetValue<Reference>(new_table.get(), "com.app.a:layout/abc");
   ASSERT_THAT(actual_ref, NotNull());
   ASSERT_TRUE(actual_ref->name);
   ASSERT_TRUE(actual_ref->id);
-  EXPECT_EQ(expected_ref.name.value(), actual_ref->name.value());
-  EXPECT_EQ(expected_ref.id.value(), actual_ref->id.value());
+  EXPECT_THAT(*actual_ref, Eq(expected_ref));
+
+  StyledString* actual_styled_str =
+      test::GetValue<StyledString>(new_table.get(), "com.app.a:string/styled");
+  ASSERT_THAT(actual_styled_str, NotNull());
+  EXPECT_THAT(actual_styled_str->value->value, Eq("hello"));
+  ASSERT_THAT(actual_styled_str->value->spans, SizeIs(1u));
+  EXPECT_THAT(*actual_styled_str->value->spans[0].name, Eq("b"));
+  EXPECT_THAT(actual_styled_str->value->spans[0].first_char, Eq(0u));
+  EXPECT_THAT(actual_styled_str->value->spans[0].last_char, Eq(4u));
 }
 
 TEST(TableProtoSerializer, SerializeFileHeader) {
@@ -132,10 +151,10 @@
 
   std::string output_str;
   {
-    std::unique_ptr<pb::CompiledFile> pb_file1 = SerializeCompiledFileToPb(f);
+    std::unique_ptr<pb::internal::CompiledFile> pb_file1 = SerializeCompiledFileToPb(f);
 
     f.name.entry = "__" + f.name.entry + "$0";
-    std::unique_ptr<pb::CompiledFile> pb_file2 = SerializeCompiledFileToPb(f);
+    std::unique_ptr<pb::internal::CompiledFile> pb_file2 = SerializeCompiledFileToPb(f);
 
     StringOutputStream out_stream(&output_str);
     CompiledFileOutputStream out_file_stream(&out_stream);
@@ -154,7 +173,7 @@
 
   // Read the first compiled file.
 
-  pb::CompiledFile new_pb_file;
+  pb::internal::CompiledFile new_pb_file;
   ASSERT_TRUE(in_file_stream.ReadCompiledFile(&new_pb_file));
 
   std::unique_ptr<ResourceFile> file = DeserializeCompiledFileFromPb(
@@ -191,7 +210,7 @@
 
 TEST(TableProtoSerializer, DeserializeCorruptHeaderSafely) {
   ResourceFile f;
-  std::unique_ptr<pb::CompiledFile> pb_file = SerializeCompiledFileToPb(f);
+  std::unique_ptr<pb::internal::CompiledFile> pb_file = SerializeCompiledFileToPb(f);
 
   const std::string expected_data = "1234";
 
@@ -213,7 +232,7 @@
   EXPECT_TRUE(in_file_stream.ReadLittleEndian32(&num_files));
   EXPECT_EQ(1u, num_files);
 
-  pb::CompiledFile new_pb_file;
+  pb::internal::CompiledFile new_pb_file;
   EXPECT_FALSE(in_file_stream.ReadCompiledFile(&new_pb_file));
 
   uint64_t offset, len;
diff --git a/tools/aapt2/readme.md b/tools/aapt2/readme.md
index c8d3617..8368f9d 100644
--- a/tools/aapt2/readme.md
+++ b/tools/aapt2/readme.md
@@ -1,5 +1,18 @@
 # Android Asset Packaging Tool 2.0 (AAPT2) release notes
 
+## Version 2.19
+- Added navigation resource type.
+- Fixed issue with resource deduplication. (bug 64397629)
+- Added a daemon mode for issuing commands. This is invoked with `aapt2 daemon`.
+  Command line arguments are separated by newlines, with an empty line signalling the
+  end of a command. Sending `EOF (Ctrl+D)` to the daemon will exit.
+- Fixed an issue where multiple permissions defined in AndroidManifest.xml would generate
+  conflicting definitions for the same Java constant in Manifest.java. Changed the implementation
+  to match that of `aapt`, which will take the last definition as the sole definition.
+  A warning is logged if such a scenario occurs. (bug 64472942)
+- Made improvements to handling of paths on Windows. This should resolve a lot of issues with
+  Unicode paths. (bug 62336414, 63830502)
+
 ## Version 2.18
 ### `aapt2 ...`
 - Fixed issue where enum values were interpreted as integers and range checked. (bug 62358540)
diff --git a/tools/aapt2/test/Builders.cpp b/tools/aapt2/test/Builders.cpp
new file mode 100644
index 0000000..8f9788e
--- /dev/null
+++ b/tools/aapt2/test/Builders.cpp
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include "test/Builders.h"
+
+#include "android-base/logging.h"
+#include "androidfw/StringPiece.h"
+
+#include "io/StringInputStream.h"
+#include "test/Common.h"
+#include "util/Util.h"
+
+using ::aapt::io::StringInputStream;
+using ::android::StringPiece;
+
+namespace aapt {
+namespace test {
+
+ResourceTableBuilder& ResourceTableBuilder::SetPackageId(const StringPiece& package_name,
+                                                         uint8_t id) {
+  ResourceTablePackage* package = table_->CreatePackage(package_name, id);
+  CHECK(package != nullptr);
+  return *this;
+}
+
+ResourceTableBuilder& ResourceTableBuilder::AddSimple(const StringPiece& name,
+                                                      const ResourceId& id) {
+  return AddValue(name, id, util::make_unique<Id>());
+}
+
+ResourceTableBuilder& ResourceTableBuilder::AddSimple(const StringPiece& name,
+                                                      const ConfigDescription& config,
+                                                      const ResourceId& id) {
+  return AddValue(name, config, id, util::make_unique<Id>());
+}
+
+ResourceTableBuilder& ResourceTableBuilder::AddReference(const StringPiece& name,
+                                                         const StringPiece& ref) {
+  return AddReference(name, {}, ref);
+}
+
+ResourceTableBuilder& ResourceTableBuilder::AddReference(const StringPiece& name,
+                                                         const ResourceId& id,
+                                                         const StringPiece& ref) {
+  return AddValue(name, id, util::make_unique<Reference>(ParseNameOrDie(ref)));
+}
+
+ResourceTableBuilder& ResourceTableBuilder::AddString(const StringPiece& name,
+                                                      const StringPiece& str) {
+  return AddString(name, {}, str);
+}
+
+ResourceTableBuilder& ResourceTableBuilder::AddString(const StringPiece& name, const ResourceId& id,
+                                                      const StringPiece& str) {
+  return AddValue(name, id, util::make_unique<String>(table_->string_pool.MakeRef(str)));
+}
+
+ResourceTableBuilder& ResourceTableBuilder::AddString(const StringPiece& name, const ResourceId& id,
+                                                      const ConfigDescription& config,
+                                                      const StringPiece& str) {
+  return AddValue(name, config, id, util::make_unique<String>(table_->string_pool.MakeRef(str)));
+}
+
+ResourceTableBuilder& ResourceTableBuilder::AddFileReference(const StringPiece& name,
+                                                             const StringPiece& path) {
+  return AddFileReference(name, {}, path);
+}
+
+ResourceTableBuilder& ResourceTableBuilder::AddFileReference(const StringPiece& name,
+                                                             const ResourceId& id,
+                                                             const StringPiece& path) {
+  return AddValue(name, id, util::make_unique<FileReference>(table_->string_pool.MakeRef(path)));
+}
+
+ResourceTableBuilder& ResourceTableBuilder::AddFileReference(const StringPiece& name,
+                                                             const StringPiece& path,
+                                                             const ConfigDescription& config) {
+  return AddValue(name, config, {},
+                  util::make_unique<FileReference>(table_->string_pool.MakeRef(path)));
+}
+
+ResourceTableBuilder& ResourceTableBuilder::AddValue(const StringPiece& name,
+                                                     std::unique_ptr<Value> value) {
+  return AddValue(name, {}, std::move(value));
+}
+
+ResourceTableBuilder& ResourceTableBuilder::AddValue(const StringPiece& name, const ResourceId& id,
+                                                     std::unique_ptr<Value> value) {
+  return AddValue(name, {}, id, std::move(value));
+}
+
+ResourceTableBuilder& ResourceTableBuilder::AddValue(const StringPiece& name,
+                                                     const ConfigDescription& config,
+                                                     const ResourceId& id,
+                                                     std::unique_ptr<Value> value) {
+  ResourceName res_name = ParseNameOrDie(name);
+  CHECK(table_->AddResourceAllowMangled(res_name, id, config, {}, std::move(value),
+                                        GetDiagnostics()));
+  return *this;
+}
+
+ResourceTableBuilder& ResourceTableBuilder::SetSymbolState(const StringPiece& name,
+                                                           const ResourceId& id, SymbolState state,
+                                                           bool allow_new) {
+  ResourceName res_name = ParseNameOrDie(name);
+  Symbol symbol;
+  symbol.state = state;
+  symbol.allow_new = allow_new;
+  CHECK(table_->SetSymbolStateAllowMangled(res_name, id, symbol, GetDiagnostics()));
+  return *this;
+}
+
+StringPool* ResourceTableBuilder::string_pool() {
+  return &table_->string_pool;
+}
+
+std::unique_ptr<ResourceTable> ResourceTableBuilder::Build() {
+  return std::move(table_);
+}
+
+std::unique_ptr<Reference> BuildReference(const StringPiece& ref, const Maybe<ResourceId>& id) {
+  std::unique_ptr<Reference> reference = util::make_unique<Reference>(ParseNameOrDie(ref));
+  reference->id = id;
+  return reference;
+}
+
+std::unique_ptr<BinaryPrimitive> BuildPrimitive(uint8_t type, uint32_t data) {
+  android::Res_value value = {};
+  value.size = sizeof(value);
+  value.dataType = type;
+  value.data = data;
+  return util::make_unique<BinaryPrimitive>(value);
+}
+
+AttributeBuilder::AttributeBuilder(bool weak) : attr_(util::make_unique<Attribute>(weak)) {
+  attr_->type_mask = android::ResTable_map::TYPE_ANY;
+}
+
+AttributeBuilder& AttributeBuilder::SetTypeMask(uint32_t typeMask) {
+  attr_->type_mask = typeMask;
+  return *this;
+}
+
+AttributeBuilder& AttributeBuilder::AddItem(const StringPiece& name, uint32_t value) {
+  attr_->symbols.push_back(
+      Attribute::Symbol{Reference(ResourceName({}, ResourceType::kId, name)), value});
+  return *this;
+}
+
+std::unique_ptr<Attribute> AttributeBuilder::Build() {
+  return std::move(attr_);
+}
+
+StyleBuilder& StyleBuilder::SetParent(const StringPiece& str) {
+  style_->parent = Reference(ParseNameOrDie(str));
+  return *this;
+}
+
+StyleBuilder& StyleBuilder::AddItem(const StringPiece& str, std::unique_ptr<Item> value) {
+  style_->entries.push_back(Style::Entry{Reference(ParseNameOrDie(str)), std::move(value)});
+  return *this;
+}
+
+StyleBuilder& StyleBuilder::AddItem(const StringPiece& str, const ResourceId& id,
+                                    std::unique_ptr<Item> value) {
+  AddItem(str, std::move(value));
+  style_->entries.back().key.id = id;
+  return *this;
+}
+
+std::unique_ptr<Style> StyleBuilder::Build() {
+  return std::move(style_);
+}
+
+StyleableBuilder& StyleableBuilder::AddItem(const StringPiece& str, const Maybe<ResourceId>& id) {
+  styleable_->entries.push_back(Reference(ParseNameOrDie(str)));
+  styleable_->entries.back().id = id;
+  return *this;
+}
+
+std::unique_ptr<Styleable> StyleableBuilder::Build() {
+  return std::move(styleable_);
+}
+
+std::unique_ptr<xml::XmlResource> BuildXmlDom(const StringPiece& str) {
+  std::string input = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+  input.append(str.data(), str.size());
+  StringInputStream in(input);
+  StdErrDiagnostics diag;
+  std::unique_ptr<xml::XmlResource> doc = xml::Inflate(&in, &diag, Source("test.xml"));
+  CHECK(doc != nullptr && doc->root != nullptr) << "failed to parse inline XML string";
+  return doc;
+}
+
+std::unique_ptr<xml::XmlResource> BuildXmlDomForPackageName(IAaptContext* context,
+                                                            const StringPiece& str) {
+  std::unique_ptr<xml::XmlResource> doc = BuildXmlDom(str);
+  doc->file.name.package = context->GetCompilationPackage();
+  return doc;
+}
+
+}  // namespace test
+}  // namespace aapt
diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h
index 6b82076..d9f3912 100644
--- a/tools/aapt2/test/Builders.h
+++ b/tools/aapt2/test/Builders.h
@@ -19,13 +19,13 @@
 
 #include <memory>
 
-#include "android-base/logging.h"
 #include "android-base/macros.h"
 
+#include "Resource.h"
 #include "ResourceTable.h"
 #include "ResourceValues.h"
-#include "test/Common.h"
-#include "util/Util.h"
+#include "process/IResourceTableConsumer.h"
+#include "util/Maybe.h"
 #include "xml/XmlDom.h"
 
 namespace aapt {
@@ -35,97 +35,37 @@
  public:
   ResourceTableBuilder() = default;
 
-  StringPool* string_pool() { return &table_->string_pool; }
-
-  ResourceTableBuilder& SetPackageId(const android::StringPiece& package_name, uint8_t id) {
-    ResourceTablePackage* package = table_->CreatePackage(package_name, id);
-    CHECK(package != nullptr);
-    return *this;
-  }
-
-  ResourceTableBuilder& AddSimple(const android::StringPiece& name, const ResourceId& id = {}) {
-    return AddValue(name, id, util::make_unique<Id>());
-  }
-
+  ResourceTableBuilder& SetPackageId(const android::StringPiece& package_name, uint8_t id);
+  ResourceTableBuilder& AddSimple(const android::StringPiece& name, const ResourceId& id = {});
   ResourceTableBuilder& AddSimple(const android::StringPiece& name, const ConfigDescription& config,
-                                  const ResourceId& id = {}) {
-    return AddValue(name, config, id, util::make_unique<Id>());
-  }
-
+                                  const ResourceId& id = {});
   ResourceTableBuilder& AddReference(const android::StringPiece& name,
-                                     const android::StringPiece& ref) {
-    return AddReference(name, {}, ref);
-  }
-
+                                     const android::StringPiece& ref);
   ResourceTableBuilder& AddReference(const android::StringPiece& name, const ResourceId& id,
-                                     const android::StringPiece& ref) {
-    return AddValue(name, id, util::make_unique<Reference>(ParseNameOrDie(ref)));
-  }
-
+                                     const android::StringPiece& ref);
   ResourceTableBuilder& AddString(const android::StringPiece& name,
-                                  const android::StringPiece& str) {
-    return AddString(name, {}, str);
-  }
-
+                                  const android::StringPiece& str);
   ResourceTableBuilder& AddString(const android::StringPiece& name, const ResourceId& id,
-                                  const android::StringPiece& str) {
-    return AddValue(
-        name, id, util::make_unique<String>(table_->string_pool.MakeRef(str)));
-  }
-
+                                  const android::StringPiece& str);
   ResourceTableBuilder& AddString(const android::StringPiece& name, const ResourceId& id,
-                                  const ConfigDescription& config,
-                                  const android::StringPiece& str) {
-    return AddValue(name, config, id, util::make_unique<String>(
-                                          table_->string_pool.MakeRef(str)));
-  }
-
+                                  const ConfigDescription& config, const android::StringPiece& str);
   ResourceTableBuilder& AddFileReference(const android::StringPiece& name,
-                                         const android::StringPiece& path) {
-    return AddFileReference(name, {}, path);
-  }
-
+                                         const android::StringPiece& path);
   ResourceTableBuilder& AddFileReference(const android::StringPiece& name, const ResourceId& id,
-                                         const android::StringPiece& path) {
-    return AddValue(name, id, util::make_unique<FileReference>(
-                                  table_->string_pool.MakeRef(path)));
-  }
-
+                                         const android::StringPiece& path);
   ResourceTableBuilder& AddFileReference(const android::StringPiece& name,
                                          const android::StringPiece& path,
-                                         const ConfigDescription& config) {
-    return AddValue(name, config, {}, util::make_unique<FileReference>(
-                                          table_->string_pool.MakeRef(path)));
-  }
-
-  ResourceTableBuilder& AddValue(const android::StringPiece& name, std::unique_ptr<Value> value) {
-    return AddValue(name, {}, std::move(value));
-  }
-
+                                         const ConfigDescription& config);
+  ResourceTableBuilder& AddValue(const android::StringPiece& name, std::unique_ptr<Value> value);
   ResourceTableBuilder& AddValue(const android::StringPiece& name, const ResourceId& id,
-                                 std::unique_ptr<Value> value) {
-    return AddValue(name, {}, id, std::move(value));
-  }
-
+                                 std::unique_ptr<Value> value);
   ResourceTableBuilder& AddValue(const android::StringPiece& name, const ConfigDescription& config,
-                                 const ResourceId& id, std::unique_ptr<Value> value) {
-    ResourceName res_name = ParseNameOrDie(name);
-    CHECK(table_->AddResourceAllowMangled(res_name, id, config, {}, std::move(value),
-                                          GetDiagnostics()));
-    return *this;
-  }
-
+                                 const ResourceId& id, std::unique_ptr<Value> value);
   ResourceTableBuilder& SetSymbolState(const android::StringPiece& name, const ResourceId& id,
-                                       SymbolState state, bool allow_new = false) {
-    ResourceName res_name = ParseNameOrDie(name);
-    Symbol symbol;
-    symbol.state = state;
-    symbol.allow_new = allow_new;
-    CHECK(table_->SetSymbolStateAllowMangled(res_name, id, symbol, GetDiagnostics()));
-    return *this;
-  }
+                                       SymbolState state, bool allow_new = false);
 
-  std::unique_ptr<ResourceTable> Build() { return std::move(table_); }
+  StringPool* string_pool();
+  std::unique_ptr<ResourceTable> Build();
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ResourceTableBuilder);
@@ -133,29 +73,16 @@
   std::unique_ptr<ResourceTable> table_ = util::make_unique<ResourceTable>();
 };
 
-inline std::unique_ptr<Reference> BuildReference(const android::StringPiece& ref,
-                                                 const Maybe<ResourceId>& id = {}) {
-  std::unique_ptr<Reference> reference =
-      util::make_unique<Reference>(ParseNameOrDie(ref));
-  reference->id = id;
-  return reference;
-}
-
-inline std::unique_ptr<BinaryPrimitive> BuildPrimitive(uint8_t type,
-                                                       uint32_t data) {
-  android::Res_value value = {};
-  value.size = sizeof(value);
-  value.dataType = type;
-  value.data = data;
-  return util::make_unique<BinaryPrimitive>(value);
-}
+std::unique_ptr<Reference> BuildReference(const android::StringPiece& ref,
+                                          const Maybe<ResourceId>& id = {});
+std::unique_ptr<BinaryPrimitive> BuildPrimitive(uint8_t type, uint32_t data);
 
 template <typename T>
 class ValueBuilder {
  public:
   template <typename... Args>
-  explicit ValueBuilder(Args&&... args)
-      : value_(new T{std::forward<Args>(args)...}) {}
+  explicit ValueBuilder(Args&&... args) : value_(new T{std::forward<Args>(args)...}) {
+  }
 
   template <typename... Args>
   ValueBuilder& SetSource(Args&&... args) {
@@ -168,7 +95,9 @@
     return *this;
   }
 
-  std::unique_ptr<Value> Build() { return std::move(value_); }
+  std::unique_ptr<Value> Build() {
+    return std::move(value_);
+  }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ValueBuilder);
@@ -178,23 +107,10 @@
 
 class AttributeBuilder {
  public:
-  explicit AttributeBuilder(bool weak = false)
-      : attr_(util::make_unique<Attribute>(weak)) {
-    attr_->type_mask = android::ResTable_map::TYPE_ANY;
-  }
-
-  AttributeBuilder& SetTypeMask(uint32_t typeMask) {
-    attr_->type_mask = typeMask;
-    return *this;
-  }
-
-  AttributeBuilder& AddItem(const android::StringPiece& name, uint32_t value) {
-    attr_->symbols.push_back(Attribute::Symbol{
-        Reference(ResourceName({}, ResourceType::kId, name)), value});
-    return *this;
-  }
-
-  std::unique_ptr<Attribute> Build() { return std::move(attr_); }
+  explicit AttributeBuilder(bool weak = false);
+  AttributeBuilder& SetTypeMask(uint32_t typeMask);
+  AttributeBuilder& AddItem(const android::StringPiece& name, uint32_t value);
+  std::unique_ptr<Attribute> Build();
 
  private:
   DISALLOW_COPY_AND_ASSIGN(AttributeBuilder);
@@ -205,27 +121,11 @@
 class StyleBuilder {
  public:
   StyleBuilder() = default;
-
-  StyleBuilder& SetParent(const android::StringPiece& str) {
-    style_->parent = Reference(ParseNameOrDie(str));
-    return *this;
-  }
-
-  StyleBuilder& AddItem(const android::StringPiece& str, std::unique_ptr<Item> value) {
-    style_->entries.push_back(Style::Entry{Reference(ParseNameOrDie(str)), std::move(value)});
-    return *this;
-  }
-
+  StyleBuilder& SetParent(const android::StringPiece& str);
+  StyleBuilder& AddItem(const android::StringPiece& str, std::unique_ptr<Item> value);
   StyleBuilder& AddItem(const android::StringPiece& str, const ResourceId& id,
-                        std::unique_ptr<Item> value) {
-    AddItem(str, std::move(value));
-    style_->entries.back().key.id = id;
-    return *this;
-  }
-
-  std::unique_ptr<Style> Build() {
-    return std::move(style_);
-  }
+                        std::unique_ptr<Item> value);
+  std::unique_ptr<Style> Build();
 
  private:
   DISALLOW_COPY_AND_ASSIGN(StyleBuilder);
@@ -236,14 +136,8 @@
 class StyleableBuilder {
  public:
   StyleableBuilder() = default;
-
-  StyleableBuilder& AddItem(const android::StringPiece& str, const Maybe<ResourceId>& id = {}) {
-    styleable_->entries.push_back(Reference(ParseNameOrDie(str)));
-    styleable_->entries.back().id = id;
-    return *this;
-  }
-
-  std::unique_ptr<Styleable> Build() { return std::move(styleable_); }
+  StyleableBuilder& AddItem(const android::StringPiece& str, const Maybe<ResourceId>& id = {});
+  std::unique_ptr<Styleable> Build();
 
  private:
   DISALLOW_COPY_AND_ASSIGN(StyleableBuilder);
@@ -251,22 +145,9 @@
   std::unique_ptr<Styleable> styleable_ = util::make_unique<Styleable>();
 };
 
-inline std::unique_ptr<xml::XmlResource> BuildXmlDom(const android::StringPiece& str) {
-  std::stringstream in;
-  in << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" << str;
-  StdErrDiagnostics diag;
-  std::unique_ptr<xml::XmlResource> doc =
-      xml::Inflate(&in, &diag, Source("test.xml"));
-  CHECK(doc != nullptr) << "failed to parse inline XML string";
-  return doc;
-}
-
-inline std::unique_ptr<xml::XmlResource> BuildXmlDomForPackageName(
-    IAaptContext* context, const android::StringPiece& str) {
-  std::unique_ptr<xml::XmlResource> doc = BuildXmlDom(str);
-  doc->file.name.package = context->GetCompilationPackage();
-  return doc;
-}
+std::unique_ptr<xml::XmlResource> BuildXmlDom(const android::StringPiece& str);
+std::unique_ptr<xml::XmlResource> BuildXmlDomForPackageName(IAaptContext* context,
+                                                            const android::StringPiece& str);
 
 }  // namespace test
 }  // namespace aapt
diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h
index d7b46ca..e6b38c0 100644
--- a/tools/aapt2/test/Common.h
+++ b/tools/aapt2/test/Common.h
@@ -142,10 +142,97 @@
   return android::StringPiece16(arg) == a;
 }
 
-MATCHER_P(ValueEq, a,
-          std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) {
-  return arg.Equals(&a);
-}
+class ValueEq {
+ public:
+  template <typename arg_type>
+  class BaseImpl : public ::testing::MatcherInterface<arg_type> {
+    BaseImpl(const BaseImpl&) = default;
+
+    void DescribeTo(::std::ostream* os) const override {
+      *os << "is equal to " << *expected_;
+    }
+
+    void DescribeNegationTo(::std::ostream* os) const override {
+      *os << "is not equal to " << *expected_;
+    }
+
+   protected:
+    BaseImpl(const Value* expected) : expected_(expected) {
+    }
+
+    const Value* expected_;
+  };
+
+  template <typename T, bool>
+  class Impl {};
+
+  template <typename T>
+  class Impl<T, false> : public ::testing::MatcherInterface<T> {
+   public:
+    explicit Impl(const Value* expected) : expected_(expected) {
+    }
+
+    bool MatchAndExplain(T x, ::testing::MatchResultListener* listener) const override {
+      return expected_->Equals(&x);
+    }
+
+    void DescribeTo(::std::ostream* os) const override {
+      *os << "is equal to " << *expected_;
+    }
+
+    void DescribeNegationTo(::std::ostream* os) const override {
+      *os << "is not equal to " << *expected_;
+    }
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(Impl);
+
+    const Value* expected_;
+  };
+
+  template <typename T>
+  class Impl<T, true> : public ::testing::MatcherInterface<T> {
+   public:
+    explicit Impl(const Value* expected) : expected_(expected) {
+    }
+
+    bool MatchAndExplain(T x, ::testing::MatchResultListener* listener) const override {
+      return expected_->Equals(x);
+    }
+
+    void DescribeTo(::std::ostream* os) const override {
+      *os << "is equal to " << *expected_;
+    }
+
+    void DescribeNegationTo(::std::ostream* os) const override {
+      *os << "is not equal to " << *expected_;
+    }
+
+   private:
+    DISALLOW_COPY_AND_ASSIGN(Impl);
+
+    const Value* expected_;
+  };
+
+  ValueEq(const Value& expected) : expected_(&expected) {
+  }
+  ValueEq(const Value* expected) : expected_(expected) {
+  }
+  ValueEq(const ValueEq&) = default;
+
+  template <typename T>
+  operator ::testing::Matcher<T>() const {
+    return ::testing::Matcher<T>(new Impl<T, std::is_pointer<T>::value>(expected_));
+  }
+
+ private:
+  const Value* expected_;
+};
+
+// MATCHER_P(ValueEq, a,
+//          std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) {
+//  return arg.Equals(&a);
+//}
 
 MATCHER_P(StrValueEq, a,
           std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) {
diff --git a/tools/aapt2/unflatten/BinaryResourceParser.cpp b/tools/aapt2/unflatten/BinaryResourceParser.cpp
index 728d1f4..892aee6 100644
--- a/tools/aapt2/unflatten/BinaryResourceParser.cpp
+++ b/tools/aapt2/unflatten/BinaryResourceParser.cpp
@@ -544,7 +544,7 @@
     const ResTable_map_entry* map) {
   std::unique_ptr<Array> array = util::make_unique<Array>();
   for (const ResTable_map& map_entry : map) {
-    array->items.push_back(ParseValue(name, config, map_entry.value));
+    array->elements.push_back(ParseValue(name, config, map_entry.value));
   }
   return array;
 }
diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp
index 1bf2594..bf8dc4d 100644
--- a/tools/aapt2/util/Files.cpp
+++ b/tools/aapt2/util/Files.cpp
@@ -27,6 +27,8 @@
 #include "android-base/errors.h"
 #include "android-base/file.h"
 #include "android-base/logging.h"
+#include "android-base/unique_fd.h"
+#include "android-base/utf8.h"
 
 #include "util/Util.h"
 
@@ -35,14 +37,32 @@
 #include <direct.h>
 #endif
 
-using android::StringPiece;
+using ::android::FileMap;
+using ::android::StringPiece;
+using ::android::base::ReadFileToString;
+using ::android::base::SystemErrorCodeToString;
+using ::android::base::unique_fd;
 
 namespace aapt {
 namespace file {
 
-FileType GetFileType(const StringPiece& path) {
+FileType GetFileType(const std::string& path) {
+// TODO(adamlesinski): I'd like to move this to ::android::base::utf8 but Windows does some macro
+// trickery with 'stat' and things don't override very well.
+#ifdef _WIN32
+  std::wstring path_utf16;
+  if (!::android::base::UTF8PathToWindowsLongPath(path.c_str(), &path_utf16)) {
+    return FileType::kNonexistant;
+  }
+
+  struct _stat64 sb;
+  int result = _wstat64(path_utf16.c_str(), &sb);
+#else
   struct stat sb;
-  if (stat(path.data(), &sb) < 0) {
+  int result = stat(path.c_str(), &sb);
+#endif
+
+  if (result == -1) {
     if (errno == ENOENT || errno == ENOTDIR) {
       return FileType::kNonexistant;
     }
@@ -72,27 +92,20 @@
   }
 }
 
-inline static int MkdirImpl(const StringPiece& path) {
-#ifdef _WIN32
-  return _mkdir(path.to_string().c_str());
-#else
-  return mkdir(path.to_string().c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP);
-#endif
-}
-
-bool mkdirs(const StringPiece& path) {
-  const char* start = path.begin();
-  const char* end = path.end();
-  for (const char* current = start; current != end; ++current) {
-    if (*current == sDirSep && current != start) {
-      StringPiece parent_path(start, current - start);
-      int result = MkdirImpl(parent_path);
-      if (result < 0 && errno != EEXIST) {
-        return false;
-      }
+bool mkdirs(const std::string& path) {
+  constexpr const mode_t mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP;
+  // Start after the first character so that we don't consume the root '/'.
+  // This is safe to do with unicode because '/' will never match with a continuation character.
+  size_t current_pos = 1u;
+  while ((current_pos = path.find(sDirSep, current_pos)) != std::string::npos) {
+    std::string parent_path = path.substr(0, current_pos);
+    int result = ::android::base::utf8::mkdir(parent_path.c_str(), mode);
+    if (result < 0 && errno != EEXIST) {
+      return false;
     }
+    current_pos += 1;
   }
-  return MkdirImpl(path) == 0 || errno == EEXIST;
+  return ::android::base::utf8::mkdir(path.c_str(), mode) == 0 || errno == EEXIST;
 }
 
 StringPiece GetStem(const StringPiece& path) {
@@ -129,10 +142,8 @@
 
 void AppendPath(std::string* base, StringPiece part) {
   CHECK(base != nullptr);
-  const bool base_has_trailing_sep =
-      (!base->empty() && *(base->end() - 1) == sDirSep);
-  const bool part_has_leading_sep =
-      (!part.empty() && *(part.begin()) == sDirSep);
+  const bool base_has_trailing_sep = (!base->empty() && *(base->end() - 1) == sDirSep);
+  const bool part_has_leading_sep = (!part.empty() && *(part.begin()) == sDirSep);
   if (base_has_trailing_sep && part_has_leading_sep) {
     // Remove the part's leading sep
     part = part.substr(1, part.size() - 1);
@@ -151,31 +162,34 @@
   return out_path;
 }
 
-Maybe<android::FileMap> MmapPath(const StringPiece& path,
-                                 std::string* out_error) {
-  std::unique_ptr<FILE, decltype(fclose)*> f = {fopen(path.data(), "rb"),
-                                                fclose};
-  if (!f) {
-    if (out_error) *out_error = android::base::SystemErrorCodeToString(errno);
+Maybe<FileMap> MmapPath(const std::string& path, std::string* out_error) {
+  int flags = O_RDONLY | O_CLOEXEC | O_BINARY;
+  unique_fd fd(TEMP_FAILURE_RETRY(::android::base::utf8::open(path.c_str(), flags)));
+  if (fd == -1) {
+    if (out_error) {
+      *out_error = SystemErrorCodeToString(errno);
+    }
     return {};
   }
 
-  int fd = fileno(f.get());
-
   struct stat filestats = {};
   if (fstat(fd, &filestats) != 0) {
-    if (out_error) *out_error = android::base::SystemErrorCodeToString(errno);
+    if (out_error) {
+      *out_error = SystemErrorCodeToString(errno);
+    }
     return {};
   }
 
-  android::FileMap filemap;
+  FileMap filemap;
   if (filestats.st_size == 0) {
     // mmap doesn't like a length of 0. Instead we return an empty FileMap.
     return std::move(filemap);
   }
 
-  if (!filemap.create(path.data(), fd, 0, filestats.st_size, true)) {
-    if (out_error) *out_error = android::base::SystemErrorCodeToString(errno);
+  if (!filemap.create(path.c_str(), fd, 0, filestats.st_size, true)) {
+    if (out_error) {
+      *out_error = SystemErrorCodeToString(errno);
+    }
     return {};
   }
   return std::move(filemap);
@@ -184,7 +198,7 @@
 bool AppendArgsFromFile(const StringPiece& path, std::vector<std::string>* out_arglist,
                         std::string* out_error) {
   std::string contents;
-  if (!android::base::ReadFileToString(path.to_string(), &contents, true /*follow_symlinks*/)) {
+  if (!ReadFileToString(path.to_string(), &contents, true /*follow_symlinks*/)) {
     if (out_error) {
       *out_error = "failed to read argument-list file";
     }
@@ -270,7 +284,7 @@
   const std::string root_dir = path.to_string();
   std::unique_ptr<DIR, decltype(closedir)*> d(opendir(root_dir.data()), closedir);
   if (!d) {
-    diag->Error(DiagMessage() << android::base::SystemErrorCodeToString(errno));
+    diag->Error(DiagMessage() << SystemErrorCodeToString(errno));
     return {};
   }
 
diff --git a/tools/aapt2/util/Files.h b/tools/aapt2/util/Files.h
index b3b1e48..b26e4fa 100644
--- a/tools/aapt2/util/Files.h
+++ b/tools/aapt2/util/Files.h
@@ -34,8 +34,10 @@
 
 #ifdef _WIN32
 constexpr const char sDirSep = '\\';
+constexpr const char sPathSep = ';';
 #else
 constexpr const char sDirSep = '/';
+constexpr const char sPathSep = ':';
 #endif
 
 enum class FileType {
@@ -50,79 +52,56 @@
   kSocket,
 };
 
-FileType GetFileType(const android::StringPiece& path);
+FileType GetFileType(const std::string& path);
 
-/*
- * Appends a path to `base`, separated by the directory separator.
- */
+// Appends a path to `base`, separated by the directory separator.
 void AppendPath(std::string* base, android::StringPiece part);
 
-/*
- * Makes all the directories in `path`. The last element in the path
- * is interpreted as a directory.
- */
-bool mkdirs(const android::StringPiece& path);
+// Makes all the directories in `path`. The last element in the path is interpreted as a directory.
+bool mkdirs(const std::string& path);
 
-/**
- * Returns all but the last part of the path.
- */
+// Returns all but the last part of the path.
 android::StringPiece GetStem(const android::StringPiece& path);
 
-/**
- * Returns the last part of the path with extension.
- */
+// Returns the last part of the path with extension.
 android::StringPiece GetFilename(const android::StringPiece& path);
 
-/**
- * Returns the extension of the path. This is the entire string after
- * the first '.' of the last part of the path.
- */
+// Returns the extension of the path. This is the entire string after the first '.' of the last part
+// of the path.
 android::StringPiece GetExtension(const android::StringPiece& path);
 
-/**
- * Converts a package name (com.android.app) to a path: com/android/app
- */
+// Converts a package name (com.android.app) to a path: com/android/app
 std::string PackageToPath(const android::StringPiece& package);
 
-/**
- * Creates a FileMap for the file at path.
- */
-Maybe<android::FileMap> MmapPath(const android::StringPiece& path, std::string* out_error);
+// Creates a FileMap for the file at path.
+Maybe<android::FileMap> MmapPath(const std::string& path, std::string* out_error);
 
-/**
- * Reads the file at path and appends each line to the outArgList vector.
- */
+// Reads the file at path and appends each line to the outArgList vector.
 bool AppendArgsFromFile(const android::StringPiece& path, std::vector<std::string>* out_arglist,
                         std::string* out_error);
 
-/*
- * Filter that determines which resource files/directories are
- * processed by AAPT. Takes a pattern string supplied by the user.
- * Pattern format is specified in the FileFilter::SetPattern() method.
- */
+// Filter that determines which resource files/directories are
+// processed by AAPT. Takes a pattern string supplied by the user.
+// Pattern format is specified in the FileFilter::SetPattern() method.
 class FileFilter {
  public:
   explicit FileFilter(IDiagnostics* diag) : diag_(diag) {}
 
-  /*
-   * Patterns syntax:
-   * - Delimiter is :
-   * - Entry can start with the flag ! to avoid printing a warning
-   *   about the file being ignored.
-   * - Entry can have the flag "<dir>" to match only directories
-   *   or <file> to match only files. Default is to match both.
-   * - Entry can be a simplified glob "<prefix>*" or "*<suffix>"
-   *   where prefix/suffix must have at least 1 character (so that
-   *   we don't match a '*' catch-all pattern.)
-   * - The special filenames "." and ".." are always ignored.
-   * - Otherwise the full string is matched.
-   * - match is not case-sensitive.
-   */
+  // Patterns syntax:
+  // - Delimiter is :
+  // - Entry can start with the flag ! to avoid printing a warning
+  //   about the file being ignored.
+  // - Entry can have the flag "<dir>" to match only directories
+  //   or <file> to match only files. Default is to match both.
+  // - Entry can be a simplified glob "<prefix>*" or "*<suffix>"
+  //   where prefix/suffix must have at least 1 character (so that
+  //   we don't match a '*' catch-all pattern.)
+  // - The special filenames "." and ".." are always ignored.
+  // - Otherwise the full string is matched.
+  // - match is not case-sensitive.
   bool SetPattern(const android::StringPiece& pattern);
 
-  /**
-   * Applies the filter, returning true for pass, false for fail.
-   */
+  // Applies the filter, returning true for pass, false for fail.
   bool operator()(const std::string& filename, FileType type) const;
 
  private:
diff --git a/tools/aapt2/util/Util.h b/tools/aapt2/util/Util.h
index ad3989e..8f021ab 100644
--- a/tools/aapt2/util/Util.h
+++ b/tools/aapt2/util/Util.h
@@ -228,6 +228,12 @@
  public:
   class iterator {
    public:
+    using reference = android::StringPiece&;
+    using value_type = android::StringPiece;
+    using difference_type = size_t;
+    using pointer = android::StringPiece*;
+    using iterator_category = std::forward_iterator_tag;
+
     iterator(const iterator&) = default;
     iterator& operator=(const iterator&) = default;
 
@@ -250,9 +256,13 @@
 
   Tokenizer(android::StringPiece str, char sep);
 
-  iterator begin() { return begin_; }
+  iterator begin() const {
+    return begin_;
+  }
 
-  iterator end() { return end_; }
+  iterator end() const {
+    return end_;
+  }
 
  private:
   const iterator begin_;
diff --git a/tools/aapt2/xml/XmlActionExecutor.cpp b/tools/aapt2/xml/XmlActionExecutor.cpp
index 352a933..cc664a5 100644
--- a/tools/aapt2/xml/XmlActionExecutor.cpp
+++ b/tools/aapt2/xml/XmlActionExecutor.cpp
@@ -78,7 +78,7 @@
                                 XmlResource* doc) const {
   SourcePathDiagnostics source_diag(doc->file.source, diag);
 
-  Element* el = FindRootElement(doc);
+  Element* el = doc->root.get();
   if (!el) {
     if (policy == XmlActionExecutorPolicy::kWhitelist) {
       source_diag.Error(DiagMessage() << "no root XML tag found");
diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp
index 885ab3e..cbb652e 100644
--- a/tools/aapt2/xml/XmlDom.cpp
+++ b/tools/aapt2/xml/XmlDom.cpp
@@ -29,8 +29,9 @@
 #include "XmlPullParser.h"
 #include "util/Util.h"
 
-using android::StringPiece;
-using android::StringPiece16;
+using ::aapt::io::InputStream;
+using ::android::StringPiece;
+using ::android::StringPiece16;
 
 namespace aapt {
 namespace xml {
@@ -38,17 +39,15 @@
 constexpr char kXmlNamespaceSep = 1;
 
 struct Stack {
-  std::unique_ptr<xml::Node> root;
-  std::stack<xml::Node*> node_stack;
+  std::unique_ptr<xml::Element> root;
+  std::stack<xml::Element*> node_stack;
+  std::unique_ptr<xml::Element> pending_element;
   std::string pending_comment;
   std::unique_ptr<xml::Text> last_text_node;
 };
 
-/**
- * Extracts the namespace and name of an expanded element or attribute name.
- */
-static void SplitName(const char* name, std::string* out_ns,
-                      std::string* out_name) {
+// Extracts the namespace and name of an expanded element or attribute name.
+static void SplitName(const char* name, std::string* out_ns, std::string* out_name) {
   const char* p = name;
   while (*p != 0 && *p != kXmlNamespaceSep) {
     p++;
@@ -66,6 +65,7 @@
 static void FinishPendingText(Stack* stack) {
   if (stack->last_text_node != nullptr) {
     if (!stack->last_text_node->text.empty()) {
+      CHECK(!stack->node_stack.empty());
       stack->node_stack.top()->AppendChild(std::move(stack->last_text_node));
     } else {
       // Drop an empty text node.
@@ -74,48 +74,27 @@
   }
 }
 
-static void AddToStack(Stack* stack, XML_Parser parser,
-                       std::unique_ptr<Node> node) {
-  node->line_number = XML_GetCurrentLineNumber(parser);
-  node->column_number = XML_GetCurrentColumnNumber(parser);
-
-  Node* this_node = node.get();
-  if (!stack->node_stack.empty()) {
-    stack->node_stack.top()->AppendChild(std::move(node));
-  } else {
-    stack->root = std::move(node);
-  }
-
-  if (!NodeCast<Text>(this_node)) {
-    stack->node_stack.push(this_node);
-  }
-}
-
-static void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix,
-                                          const char* uri) {
+static void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix, const char* uri) {
   XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
   Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
   FinishPendingText(stack);
 
-  std::unique_ptr<Namespace> ns = util::make_unique<Namespace>();
-  if (prefix) {
-    ns->namespace_prefix = prefix;
-  }
+  NamespaceDecl decl;
+  decl.line_number = XML_GetCurrentLineNumber(parser);
+  decl.column_number = XML_GetCurrentColumnNumber(parser);
+  decl.prefix = prefix ? prefix : "";
+  decl.uri = uri ? uri : "";
 
-  if (uri) {
-    ns->namespace_uri = uri;
+  if (stack->pending_element == nullptr) {
+    stack->pending_element = util::make_unique<Element>();
   }
-
-  AddToStack(stack, parser, std::move(ns));
+  stack->pending_element->namespace_decls.push_back(std::move(decl));
 }
 
-static void XMLCALL EndNamespaceHandler(void* user_data, const char* prefix) {
+static void XMLCALL EndNamespaceHandler(void* user_data, const char* /*prefix*/) {
   XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
   Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
   FinishPendingText(stack);
-
-  CHECK(!stack->node_stack.empty());
-  stack->node_stack.pop();
 }
 
 static bool less_attribute(const Attribute& lhs, const Attribute& rhs) {
@@ -123,28 +102,42 @@
          std::tie(rhs.namespace_uri, rhs.name, rhs.value);
 }
 
-static void XMLCALL StartElementHandler(void* user_data, const char* name,
-                                        const char** attrs) {
+static void XMLCALL StartElementHandler(void* user_data, const char* name, const char** attrs) {
   XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
   Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
   FinishPendingText(stack);
 
-  std::unique_ptr<Element> el = util::make_unique<Element>();
+  std::unique_ptr<Element> el;
+  if (stack->pending_element != nullptr) {
+    el = std::move(stack->pending_element);
+  } else {
+    el = util::make_unique<Element>();
+  }
+
+  el->line_number = XML_GetCurrentLineNumber(parser);
+  el->column_number = XML_GetCurrentColumnNumber(parser);
+  el->comment = std::move(stack->pending_comment);
+
   SplitName(name, &el->namespace_uri, &el->name);
 
   while (*attrs) {
     Attribute attribute;
     SplitName(*attrs++, &attribute.namespace_uri, &attribute.name);
     attribute.value = *attrs++;
-
-    // Insert in sorted order.
-    auto iter = std::lower_bound(el->attributes.begin(), el->attributes.end(), attribute,
-                                 less_attribute);
-    el->attributes.insert(iter, std::move(attribute));
+    el->attributes.push_back(std::move(attribute));
   }
 
-  el->comment = std::move(stack->pending_comment);
-  AddToStack(stack, parser, std::move(el));
+  // Sort the attributes.
+  std::sort(el->attributes.begin(), el->attributes.end(), less_attribute);
+
+  // Add to the stack.
+  Element* this_el = el.get();
+  if (!stack->node_stack.empty()) {
+    stack->node_stack.top()->AppendChild(std::move(el));
+  } else {
+    stack->root = std::move(el);
+  }
+  stack->node_stack.push(this_el);
 }
 
 static void XMLCALL EndElementHandler(void* user_data, const char* name) {
@@ -189,40 +182,41 @@
   stack->pending_comment += comment;
 }
 
-std::unique_ptr<XmlResource> Inflate(std::istream* in, IDiagnostics* diag, const Source& source) {
+std::unique_ptr<XmlResource> Inflate(InputStream* in, IDiagnostics* diag, const Source& source) {
   Stack stack;
 
-  XML_Parser parser = XML_ParserCreateNS(nullptr, kXmlNamespaceSep);
-  XML_SetUserData(parser, &stack);
-  XML_UseParserAsHandlerArg(parser);
-  XML_SetElementHandler(parser, StartElementHandler, EndElementHandler);
-  XML_SetNamespaceDeclHandler(parser, StartNamespaceHandler, EndNamespaceHandler);
-  XML_SetCharacterDataHandler(parser, CharacterDataHandler);
-  XML_SetCommentHandler(parser, CommentDataHandler);
+  std::unique_ptr<std::remove_pointer<XML_Parser>::type, decltype(XML_ParserFree)*> parser = {
+      XML_ParserCreateNS(nullptr, kXmlNamespaceSep), XML_ParserFree};
+  XML_SetUserData(parser.get(), &stack);
+  XML_UseParserAsHandlerArg(parser.get());
+  XML_SetElementHandler(parser.get(), StartElementHandler, EndElementHandler);
+  XML_SetNamespaceDeclHandler(parser.get(), StartNamespaceHandler, EndNamespaceHandler);
+  XML_SetCharacterDataHandler(parser.get(), CharacterDataHandler);
+  XML_SetCommentHandler(parser.get(), CommentDataHandler);
 
-  char buffer[1024];
-  while (!in->eof()) {
-    in->read(buffer, sizeof(buffer) / sizeof(buffer[0]));
-    if (in->bad() && !in->eof()) {
-      stack.root = {};
-      diag->Error(DiagMessage(source) << strerror(errno));
-      break;
-    }
-
-    if (XML_Parse(parser, buffer, in->gcount(), in->eof()) == XML_STATUS_ERROR) {
-      stack.root = {};
-      diag->Error(DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser)))
-                  << XML_ErrorString(XML_GetErrorCode(parser)));
-      break;
+  const char* buffer = nullptr;
+  size_t buffer_size = 0;
+  while (in->Next(reinterpret_cast<const void**>(&buffer), &buffer_size)) {
+    if (XML_Parse(parser.get(), buffer, buffer_size, false) == XML_STATUS_ERROR) {
+      diag->Error(DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser.get())))
+                  << XML_ErrorString(XML_GetErrorCode(parser.get())));
+      return {};
     }
   }
 
-  XML_ParserFree(parser);
-  if (stack.root) {
-    return util::make_unique<XmlResource>(ResourceFile{{}, {}, source}, StringPool{},
-                                          std::move(stack.root));
+  if (in->HadError()) {
+    diag->Error(DiagMessage(source) << in->GetError());
+    return {};
+  } else {
+    // Finish off the parsing.
+    if (XML_Parse(parser.get(), nullptr, 0u, true) == XML_STATUS_ERROR) {
+      diag->Error(DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser.get())))
+                  << XML_ErrorString(XML_GetErrorCode(parser.get())));
+      return {};
+    }
   }
-  return {};
+  return util::make_unique<XmlResource>(ResourceFile{{}, {}, source}, StringPool{},
+                                        std::move(stack.root));
 }
 
 static void CopyAttributes(Element* el, android::ResXMLParser* parser, StringPool* out_pool) {
@@ -261,13 +255,13 @@
 std::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len, IDiagnostics* diag,
                                      const Source& source) {
   // We import the android namespace because on Windows NO_ERROR is a macro, not
-  // an enum, which
-  // causes errors when qualifying it with android::
+  // an enum, which causes errors when qualifying it with android::
   using namespace android;
 
   StringPool string_pool;
-  std::unique_ptr<Node> root;
-  std::stack<Node*> node_stack;
+  std::unique_ptr<Element> root;
+  std::stack<Element*> node_stack;
+  std::unique_ptr<Element> pending_element;
 
   ResXMLTree tree;
   if (tree.setTo(data, data_len) != NO_ERROR) {
@@ -275,57 +269,76 @@
   }
 
   ResXMLParser::event_code_t code;
-  while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT &&
-         code != ResXMLParser::END_DOCUMENT) {
+  while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT && code != ResXMLParser::END_DOCUMENT) {
     std::unique_ptr<Node> new_node;
     switch (code) {
       case ResXMLParser::START_NAMESPACE: {
-        std::unique_ptr<Namespace> node = util::make_unique<Namespace>();
+        NamespaceDecl decl;
         size_t len;
         const char16_t* str16 = tree.getNamespacePrefix(&len);
         if (str16) {
-          node->namespace_prefix = util::Utf16ToUtf8(StringPiece16(str16, len));
+          decl.prefix = util::Utf16ToUtf8(StringPiece16(str16, len));
         }
 
         str16 = tree.getNamespaceUri(&len);
         if (str16) {
-          node->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
+          decl.uri = util::Utf16ToUtf8(StringPiece16(str16, len));
         }
-        new_node = std::move(node);
+
+        if (pending_element == nullptr) {
+          pending_element = util::make_unique<Element>();
+        }
         break;
       }
 
       case ResXMLParser::START_TAG: {
-        std::unique_ptr<Element> node = util::make_unique<Element>();
+        std::unique_ptr<Element> el;
+        if (pending_element != nullptr) {
+          el = std::move(pending_element);
+        } else {
+          el = util::make_unique<Element>();
+          ;
+        }
+
         size_t len;
         const char16_t* str16 = tree.getElementNamespace(&len);
         if (str16) {
-          node->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
+          el->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
         }
 
         str16 = tree.getElementName(&len);
         if (str16) {
-          node->name = util::Utf16ToUtf8(StringPiece16(str16, len));
+          el->name = util::Utf16ToUtf8(StringPiece16(str16, len));
         }
 
-        CopyAttributes(node.get(), &tree, &string_pool);
+        Element* this_el = el.get();
+        CopyAttributes(el.get(), &tree, &string_pool);
 
-        new_node = std::move(node);
+        if (!node_stack.empty()) {
+          node_stack.top()->AppendChild(std::move(el));
+        } else {
+          root = std::move(el);
+        }
+        node_stack.push(this_el);
         break;
       }
 
       case ResXMLParser::TEXT: {
-        std::unique_ptr<Text> node = util::make_unique<Text>();
+        std::unique_ptr<Text> text = util::make_unique<Text>();
+        text->line_number = tree.getLineNumber();
         size_t len;
         const char16_t* str16 = tree.getText(&len);
         if (str16) {
-          node->text = util::Utf16ToUtf8(StringPiece16(str16, len));
+          text->text = util::Utf16ToUtf8(StringPiece16(str16, len));
         }
-        new_node = std::move(node);
+        CHECK(!node_stack.empty());
+        node_stack.top()->AppendChild(std::move(text));
         break;
       }
 
       case ResXMLParser::END_NAMESPACE:
+        break;
+
       case ResXMLParser::END_TAG:
         CHECK(!node_stack.empty());
         node_stack.pop();
@@ -335,74 +348,32 @@
         LOG(FATAL) << "unhandled XML chunk type";
         break;
     }
-
-    if (new_node) {
-      new_node->line_number = tree.getLineNumber();
-
-      Node* this_node = new_node.get();
-      if (!root) {
-        CHECK(node_stack.empty()) << "node stack should be empty";
-        root = std::move(new_node);
-      } else {
-        CHECK(!node_stack.empty()) << "node stack should not be empty";
-        node_stack.top()->AppendChild(std::move(new_node));
-      }
-
-      if (!NodeCast<Text>(this_node)) {
-        node_stack.push(this_node);
-      }
-    }
   }
   return util::make_unique<XmlResource>(ResourceFile{}, std::move(string_pool), std::move(root));
 }
 
-std::unique_ptr<Node> Namespace::Clone(const ElementCloneFunc& el_cloner) {
-  auto ns = util::make_unique<Namespace>();
-  ns->comment = comment;
-  ns->line_number = line_number;
-  ns->column_number = column_number;
-  ns->namespace_prefix = namespace_prefix;
-  ns->namespace_uri = namespace_uri;
-  ns->children.reserve(children.size());
-  for (const std::unique_ptr<xml::Node>& child : children) {
-    ns->AppendChild(child->Clone(el_cloner));
-  }
-  return std::move(ns);
-}
-
-Element* FindRootElement(XmlResource* doc) {
-  return FindRootElement(doc->root.get());
-}
-
 Element* FindRootElement(Node* node) {
-  if (!node) {
+  if (node == nullptr) {
     return nullptr;
   }
 
-  Element* el = nullptr;
-  while ((el = NodeCast<Element>(node)) == nullptr) {
-    if (node->children.empty()) {
-      return nullptr;
-    }
-    // We are looking for the first element, and namespaces can only have one
-    // child.
-    node = node->children.front().get();
+  while (node->parent != nullptr) {
+    node = node->parent;
   }
-  return el;
+  return NodeCast<Element>(node);
 }
 
-void Node::AppendChild(std::unique_ptr<Node> child) {
+void Element::AppendChild(std::unique_ptr<Node> child) {
   child->parent = this;
   children.push_back(std::move(child));
 }
 
-void Node::InsertChild(size_t index, std::unique_ptr<Node> child) {
+void Element::InsertChild(size_t index, std::unique_ptr<Node> child) {
   child->parent = this;
   children.insert(children.begin() + index, std::move(child));
 }
 
-Attribute* Element::FindAttribute(const StringPiece& ns,
-                                  const StringPiece& name) {
+Attribute* Element::FindAttribute(const StringPiece& ns, const StringPiece& name) {
   for (auto& attr : attributes) {
     if (ns == attr.namespace_uri && name == attr.name) {
       return &attr;
@@ -424,21 +395,11 @@
   return FindChildWithAttribute(ns, name, {}, {}, {});
 }
 
-Element* Element::FindChildWithAttribute(const StringPiece& ns,
-                                         const StringPiece& name,
-                                         const StringPiece& attr_ns,
-                                         const StringPiece& attr_name,
+Element* Element::FindChildWithAttribute(const StringPiece& ns, const StringPiece& name,
+                                         const StringPiece& attr_ns, const StringPiece& attr_name,
                                          const StringPiece& attr_value) {
-  for (auto& child_node : children) {
-    Node* child = child_node.get();
-    while (NodeCast<Namespace>(child)) {
-      if (child->children.empty()) {
-        break;
-      }
-      child = child->children[0].get();
-    }
-
-    if (Element* el = NodeCast<Element>(child)) {
+  for (auto& child : children) {
+    if (Element* el = NodeCast<Element>(child.get())) {
       if (ns == el->namespace_uri && name == el->name) {
         if (attr_ns.empty() && attr_name.empty()) {
           return el;
@@ -457,23 +418,16 @@
 std::vector<Element*> Element::GetChildElements() {
   std::vector<Element*> elements;
   for (auto& child_node : children) {
-    Node* child = child_node.get();
-    while (NodeCast<Namespace>(child)) {
-      if (child->children.empty()) {
-        break;
-      }
-      child = child->children[0].get();
-    }
-
-    if (Element* el = NodeCast<Element>(child)) {
-      elements.push_back(el);
+    if (Element* child = NodeCast<Element>(child_node.get())) {
+      elements.push_back(child);
     }
   }
   return elements;
 }
 
-std::unique_ptr<Node> Element::Clone(const ElementCloneFunc& el_cloner) {
+std::unique_ptr<Node> Element::Clone(const ElementCloneFunc& el_cloner) const {
   auto el = util::make_unique<Element>();
+  el->namespace_decls = namespace_decls;
   el->comment = comment;
   el->line_number = line_number;
   el->column_number = column_number;
@@ -488,7 +442,17 @@
   return std::move(el);
 }
 
-std::unique_ptr<Node> Text::Clone(const ElementCloneFunc&) {
+std::unique_ptr<Element> Element::CloneElement(const ElementCloneFunc& el_cloner) const {
+  return std::unique_ptr<Element>(static_cast<Element*>(Clone(el_cloner).release()));
+}
+
+void Element::Accept(Visitor* visitor) {
+  visitor->BeforeVisitElement(this);
+  visitor->Visit(this);
+  visitor->AfterVisitElement(this);
+}
+
+std::unique_ptr<Node> Text::Clone(const ElementCloneFunc&) const {
   auto t = util::make_unique<Text>();
   t->comment = comment;
   t->line_number = line_number;
@@ -497,21 +461,22 @@
   return std::move(t);
 }
 
-void PackageAwareVisitor::Visit(Namespace* ns) {
-  bool added = false;
-  if (Maybe<ExtractedPackage> maybe_package =
-          ExtractPackageFromNamespace(ns->namespace_uri)) {
-    ExtractedPackage& package = maybe_package.value();
-    package_decls_.push_back(
-        PackageDecl{ns->namespace_prefix, std::move(package)});
-    added = true;
-  }
+void Text::Accept(Visitor* visitor) {
+  visitor->Visit(this);
+}
 
-  Visitor::Visit(ns);
-
-  if (added) {
-    package_decls_.pop_back();
+void PackageAwareVisitor::BeforeVisitElement(Element* el) {
+  std::vector<PackageDecl> decls;
+  for (const NamespaceDecl& decl : el->namespace_decls) {
+    if (Maybe<ExtractedPackage> maybe_package = ExtractPackageFromNamespace(decl.uri)) {
+      decls.push_back(PackageDecl{decl.prefix, std::move(maybe_package.value())});
+    }
   }
+  package_decls_.push_back(std::move(decls));
+}
+
+void PackageAwareVisitor::AfterVisitElement(Element* el) {
+  package_decls_.pop_back();
 }
 
 Maybe<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias(
@@ -522,11 +487,16 @@
 
   const auto rend = package_decls_.rend();
   for (auto iter = package_decls_.rbegin(); iter != rend; ++iter) {
-    if (alias == iter->prefix) {
-      if (iter->package.package.empty()) {
-        return ExtractedPackage{local_package.to_string(), iter->package.private_namespace};
+    const std::vector<PackageDecl>& decls = *iter;
+    const auto rend2 = decls.rend();
+    for (auto iter2 = decls.rbegin(); iter2 != rend2; ++iter2) {
+      const PackageDecl& decl = *iter2;
+      if (alias == decl.prefix) {
+        if (decl.package.package.empty()) {
+          return ExtractedPackage{local_package.to_string(), decl.package.private_namespace};
+        }
+        return decl.package;
       }
-      return iter->package;
     }
   }
   return {};
diff --git a/tools/aapt2/xml/XmlDom.h b/tools/aapt2/xml/XmlDom.h
index 2dc99d6..1542243 100644
--- a/tools/aapt2/xml/XmlDom.h
+++ b/tools/aapt2/xml/XmlDom.h
@@ -17,7 +17,6 @@
 #ifndef AAPT_XML_DOM_H
 #define AAPT_XML_DOM_H
 
-#include <istream>
 #include <memory>
 #include <string>
 #include <vector>
@@ -27,58 +26,40 @@
 #include "Diagnostics.h"
 #include "Resource.h"
 #include "ResourceValues.h"
+#include "io/Io.h"
 #include "util/Util.h"
 #include "xml/XmlUtil.h"
 
 namespace aapt {
 namespace xml {
 
-class RawVisitor;
-
 class Element;
+class Visitor;
 
-/**
- * Base class for all XML nodes.
- */
+// Base class for all XML nodes.
 class Node {
  public:
-  Node* parent = nullptr;
-  size_t line_number = 0;
-  size_t column_number = 0;
-  std::string comment;
-  std::vector<std::unique_ptr<Node>> children;
-
   virtual ~Node() = default;
 
-  void AppendChild(std::unique_ptr<Node> child);
-  void InsertChild(size_t index, std::unique_ptr<Node> child);
-  virtual void Accept(RawVisitor* visitor) = 0;
+  Element* parent = nullptr;
+  size_t line_number = 0u;
+  size_t column_number = 0u;
+  std::string comment;
+
+  virtual void Accept(Visitor* visitor) = 0;
 
   using ElementCloneFunc = std::function<void(const Element&, Element*)>;
 
   // Clones the Node subtree, using the given function to decide how to clone an Element.
-  virtual std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) = 0;
+  virtual std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) const = 0;
 };
 
-/**
- * Base class that implements the visitor methods for a
- * subclass of Node.
- */
-template <typename Derived>
-class BaseNode : public Node {
- public:
-  virtual void Accept(RawVisitor* visitor) override;
-};
-
-/**
- * A Namespace XML node. Can only have one child.
- */
-class Namespace : public BaseNode<Namespace> {
- public:
-  std::string namespace_prefix;
-  std::string namespace_uri;
-
-  std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) override;
+// A namespace declaration (xmlns:prefix="uri").
+struct NamespaceDecl {
+  std::string prefix;
+  std::string uri;
+  size_t line_number = 0u;
+  size_t column_number = 0u;
 };
 
 struct AaptAttribute {
@@ -90,9 +71,7 @@
   Maybe<ResourceId> id;
 };
 
-/**
- * An XML attribute.
- */
+// An XML attribute.
 struct Attribute {
   std::string namespace_uri;
   std::string name;
@@ -102,41 +81,50 @@
   std::unique_ptr<Item> compiled_value;
 };
 
-/**
- * An Element XML node.
- */
-class Element : public BaseNode<Element> {
+// An Element XML node.
+class Element : public Node {
  public:
+  // Ordered namespace prefix declarations.
+  std::vector<NamespaceDecl> namespace_decls;
+
   std::string namespace_uri;
   std::string name;
   std::vector<Attribute> attributes;
+  std::vector<std::unique_ptr<Node>> children;
+
+  void AppendChild(std::unique_ptr<Node> child);
+  void InsertChild(size_t index, std::unique_ptr<Node> child);
 
   Attribute* FindAttribute(const android::StringPiece& ns, const android::StringPiece& name);
   const Attribute* FindAttribute(const android::StringPiece& ns,
                                  const android::StringPiece& name) const;
-  xml::Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name);
-  xml::Element* FindChildWithAttribute(const android::StringPiece& ns,
-                                       const android::StringPiece& name,
-                                       const android::StringPiece& attr_ns,
-                                       const android::StringPiece& attr_name,
-                                       const android::StringPiece& attr_value);
-  std::vector<xml::Element*> GetChildElements();
-  std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) override;
+  Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name);
+  Element* FindChildWithAttribute(const android::StringPiece& ns, const android::StringPiece& name,
+                                  const android::StringPiece& attr_ns,
+                                  const android::StringPiece& attr_name,
+                                  const android::StringPiece& attr_value);
+  std::vector<Element*> GetChildElements();
+
+  // Due to overriding of subtypes not working with unique_ptr, define a convenience Clone method
+  // that knows cloning an element returns an element.
+  std::unique_ptr<Element> CloneElement(const ElementCloneFunc& el_cloner) const;
+
+  std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) const override;
+
+  void Accept(Visitor* visitor) override;
 };
 
-/**
- * A Text (CDATA) XML node. Can not have any children.
- */
-class Text : public BaseNode<Text> {
+// A Text (CDATA) XML node. Can not have any children.
+class Text : public Node {
  public:
   std::string text;
 
-  std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) override;
+  std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) const override;
+
+  void Accept(Visitor* visitor) override;
 };
 
-/**
- * An XML resource with a source, name, and XML tree.
- */
+// An XML resource with a source, name, and XML tree.
 class XmlResource {
  public:
   ResourceFile file;
@@ -146,99 +134,121 @@
   // is destroyed.
   StringPool string_pool;
 
-  std::unique_ptr<xml::Node> root;
+  std::unique_ptr<xml::Element> root;
 };
 
-/**
- * Inflates an XML DOM from a text stream, logging errors to the logger.
- * Returns the root node on success, or nullptr on failure.
- */
-std::unique_ptr<XmlResource> Inflate(std::istream* in, IDiagnostics* diag, const Source& source);
+// Inflates an XML DOM from an InputStream, logging errors to the logger.
+// Returns the root node on success, or nullptr on failure.
+std::unique_ptr<XmlResource> Inflate(io::InputStream* in, IDiagnostics* diag, const Source& source);
 
-/**
- * Inflates an XML DOM from a binary ResXMLTree, logging errors to the logger.
- * Returns the root node on success, or nullptr on failure.
- */
+// Inflates an XML DOM from a binary ResXMLTree, logging errors to the logger.
+// Returns the root node on success, or nullptr on failure.
 std::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len, IDiagnostics* diag,
                                      const Source& source);
 
-Element* FindRootElement(XmlResource* doc);
 Element* FindRootElement(Node* node);
 
-/**
- * A visitor interface for the different XML Node subtypes. This will not
- * traverse into
- * children. Use Visitor for that.
- */
-class RawVisitor {
+// Visitor whose default implementation visits the children nodes of any node.
+class Visitor {
  public:
-  virtual ~RawVisitor() = default;
+  virtual ~Visitor() = default;
 
-  virtual void Visit(Namespace* node) {}
-  virtual void Visit(Element* node) {}
-  virtual void Visit(Text* text) {}
-};
+  virtual void Visit(Element* el) {
+    VisitChildren(el);
+  }
 
-/**
- * Visitor whose default implementation visits the children nodes of any node.
- */
-class Visitor : public RawVisitor {
- public:
-  using RawVisitor::Visit;
+  virtual void Visit(Text* text) {
+  }
 
-  void Visit(Namespace* node) override { VisitChildren(node); }
+ protected:
+  Visitor() = default;
 
-  void Visit(Element* node) override { VisitChildren(node); }
-
-  void Visit(Text* text) override { VisitChildren(text); }
-
-  void VisitChildren(Node* node) {
-    for (auto& child : node->children) {
+  void VisitChildren(Element* el) {
+    for (auto& child : el->children) {
       child->Accept(this);
     }
   }
+
+  virtual void BeforeVisitElement(Element* el) {
+  }
+  virtual void AfterVisitElement(Element* el) {
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(Visitor);
+
+  friend class Element;
 };
 
-/**
- * An XML DOM visitor that will record the package name for a namespace prefix.
- */
+// An XML DOM visitor that will record the package name for a namespace prefix.
 class PackageAwareVisitor : public Visitor, public IPackageDeclStack {
  public:
   using Visitor::Visit;
 
-  void Visit(Namespace* ns) override;
   Maybe<ExtractedPackage> TransformPackageAlias(
       const android::StringPiece& alias, const android::StringPiece& local_package) const override;
 
+ protected:
+  PackageAwareVisitor() = default;
+
+  void BeforeVisitElement(Element* el) override;
+  void AfterVisitElement(Element* el) override;
+
  private:
+  DISALLOW_COPY_AND_ASSIGN(PackageAwareVisitor);
+
   struct PackageDecl {
     std::string prefix;
     ExtractedPackage package;
   };
 
-  std::vector<PackageDecl> package_decls_;
+  std::vector<std::vector<PackageDecl>> package_decls_;
 };
 
-// Implementations
+namespace internal {
 
-template <typename Derived>
-void BaseNode<Derived>::Accept(RawVisitor* visitor) {
-  visitor->Visit(static_cast<Derived*>(this));
-}
+// Base class that overrides the default behaviour and does not descend into child nodes.
+class NodeCastBase : public Visitor {
+ public:
+  void Visit(Element* el) override {
+  }
+  void Visit(Text* el) override {
+  }
+
+ protected:
+  NodeCastBase() = default;
+
+  void BeforeVisitElement(Element* el) override {
+  }
+  void AfterVisitElement(Element* el) override {
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NodeCastBase);
+};
 
 template <typename T>
-class NodeCastImpl : public RawVisitor {
+class NodeCastImpl : public NodeCastBase {
  public:
-  using RawVisitor::Visit;
+  using NodeCastBase::Visit;
+
+  NodeCastImpl() = default;
 
   T* value = nullptr;
 
-  void Visit(T* v) override { value = v; }
+  void Visit(T* v) override {
+    value = v;
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NodeCastImpl);
 };
 
+}  // namespace internal
+
 template <typename T>
 T* NodeCast(Node* node) {
-  NodeCastImpl<T> visitor;
+  internal::NodeCastImpl<T> visitor;
   node->Accept(&visitor);
   return visitor.value;
 }
diff --git a/tools/aapt2/xml/XmlDom_test.cpp b/tools/aapt2/xml/XmlDom_test.cpp
index f0122e8..6ed2d61 100644
--- a/tools/aapt2/xml/XmlDom_test.cpp
+++ b/tools/aapt2/xml/XmlDom_test.cpp
@@ -16,23 +16,22 @@
 
 #include "xml/XmlDom.h"
 
-#include <sstream>
 #include <string>
 
+#include "io/StringInputStream.h"
 #include "test/Test.h"
 
+using ::aapt::io::StringInputStream;
 using ::testing::Eq;
 using ::testing::NotNull;
 using ::testing::SizeIs;
+using ::testing::StrEq;
 
 namespace aapt {
-
-constexpr const char* kXmlPreamble =
-    "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+namespace xml {
 
 TEST(XmlDomTest, Inflate) {
-  std::stringstream in(kXmlPreamble);
-  in << R"(
+  std::string input = R"(<?xml version="1.0" encoding="utf-8"?>
       <Layout xmlns:android="http://schemas.android.com/apk/res/android"
           android:layout_width="match_parent"
           android:layout_height="wrap_content">
@@ -41,26 +40,25 @@
             android:layout_height="wrap_content" />
       </Layout>)";
 
-  const Source source("test.xml");
   StdErrDiagnostics diag;
-  std::unique_ptr<xml::XmlResource> doc = xml::Inflate(&in, &diag, source);
+  StringInputStream in(input);
+  std::unique_ptr<XmlResource> doc = Inflate(&in, &diag, Source("test.xml"));
   ASSERT_THAT(doc, NotNull());
 
-  xml::Namespace* ns = xml::NodeCast<xml::Namespace>(doc->root.get());
-  ASSERT_THAT(ns, NotNull());
-  EXPECT_THAT(ns->namespace_uri, Eq(xml::kSchemaAndroid));
-  EXPECT_THAT(ns->namespace_prefix, Eq("android"));
+  Element* el = doc->root.get();
+  EXPECT_THAT(el->namespace_decls, SizeIs(1u));
+  EXPECT_THAT(el->namespace_decls[0].uri, StrEq(xml::kSchemaAndroid));
+  EXPECT_THAT(el->namespace_decls[0].prefix, StrEq("android"));
 }
 
 // Escaping is handled after parsing of the values for resource-specific values.
 TEST(XmlDomTest, ForwardEscapes) {
-  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(
+  std::unique_ptr<XmlResource> doc = test::BuildXmlDom(R"(
       <element value="\?hello" pattern="\\d{5}">\\d{5}</element>)");
 
-  xml::Element* el = xml::FindRootElement(doc.get());
-  ASSERT_THAT(el, NotNull());
+  Element* el = doc->root.get();
 
-  xml::Attribute* attr = el->FindAttribute({}, "pattern");
+  Attribute* attr = el->FindAttribute({}, "pattern");
   ASSERT_THAT(attr, NotNull());
   EXPECT_THAT(attr->value, Eq("\\\\d{5}"));
 
@@ -70,21 +68,54 @@
 
   ASSERT_THAT(el->children, SizeIs(1u));
 
-  xml::Text* text = xml::NodeCast<xml::Text>(el->children[0].get());
+  Text* text = xml::NodeCast<xml::Text>(el->children[0].get());
   ASSERT_THAT(text, NotNull());
   EXPECT_THAT(text->text, Eq("\\\\d{5}"));
 }
 
 TEST(XmlDomTest, XmlEscapeSequencesAreParsed) {
-  std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<element value="&quot;" />)");
-
-  xml::Element* el = xml::FindRootElement(doc.get());
-  ASSERT_THAT(el, NotNull());
-
-  xml::Attribute* attr = el->FindAttribute({}, "value");
+  std::unique_ptr<XmlResource> doc = test::BuildXmlDom(R"(<element value="&quot;" />)");
+  Attribute* attr = doc->root->FindAttribute({}, "value");
   ASSERT_THAT(attr, NotNull());
-
   EXPECT_THAT(attr->value, Eq("\""));
 }
 
+class TestVisitor : public PackageAwareVisitor {
+ public:
+  using PackageAwareVisitor::Visit;
+
+  void Visit(Element* el) override {
+    if (el->name == "View1") {
+      EXPECT_THAT(TransformPackageAlias("one", "local"),
+                  Eq(make_value(ExtractedPackage{"com.one", false})));
+    } else if (el->name == "View2") {
+      EXPECT_THAT(TransformPackageAlias("one", "local"),
+                  Eq(make_value(ExtractedPackage{"com.one", false})));
+      EXPECT_THAT(TransformPackageAlias("two", "local"),
+                  Eq(make_value(ExtractedPackage{"com.two", false})));
+    } else if (el->name == "View3") {
+      EXPECT_THAT(TransformPackageAlias("one", "local"),
+                  Eq(make_value(ExtractedPackage{"com.one", false})));
+      EXPECT_THAT(TransformPackageAlias("two", "local"),
+                  Eq(make_value(ExtractedPackage{"com.two", false})));
+      EXPECT_THAT(TransformPackageAlias("three", "local"),
+                  Eq(make_value(ExtractedPackage{"com.three", false})));
+    }
+  }
+};
+
+TEST(XmlDomTest, PackageAwareXmlVisitor) {
+  std::unique_ptr<XmlResource> doc = test::BuildXmlDom(R"(
+      <View1 xmlns:one="http://schemas.android.com/apk/res/com.one">
+        <View2 xmlns:two="http://schemas.android.com/apk/res/com.two">
+          <View3 xmlns:three="http://schemas.android.com/apk/res/com.three" />
+        </View2>
+      </View1>)");
+
+  Debug::DumpXml(doc.get());
+  TestVisitor visitor;
+  doc->root->Accept(&visitor);
+}
+
+}  // namespace xml
 }  // namespace aapt
diff --git a/tools/aapt2/xml/XmlPullParser.cpp b/tools/aapt2/xml/XmlPullParser.cpp
index c2a9c82..30bdc50 100644
--- a/tools/aapt2/xml/XmlPullParser.cpp
+++ b/tools/aapt2/xml/XmlPullParser.cpp
@@ -22,14 +22,15 @@
 #include "xml/XmlPullParser.h"
 #include "xml/XmlUtil.h"
 
-using android::StringPiece;
+using ::aapt::io::InputStream;
+using ::android::StringPiece;
 
 namespace aapt {
 namespace xml {
 
 constexpr char kXmlNamespaceSep = 1;
 
-XmlPullParser::XmlPullParser(std::istream& in) : in_(in), empty_(), depth_(0) {
+XmlPullParser::XmlPullParser(InputStream* in) : in_(in), empty_(), depth_(0) {
   parser_ = XML_ParserCreateNS(nullptr, kXmlNamespaceSep);
   XML_SetUserData(parser_, this);
   XML_SetElementHandler(parser_, StartElementHandler, EndElementHandler);
@@ -40,30 +41,35 @@
   event_queue_.push(EventData{Event::kStartDocument, 0, depth_++});
 }
 
-XmlPullParser::~XmlPullParser() { XML_ParserFree(parser_); }
+XmlPullParser::~XmlPullParser() {
+  XML_ParserFree(parser_);
+}
 
 XmlPullParser::Event XmlPullParser::Next() {
   const Event currentEvent = event();
-  if (currentEvent == Event::kBadDocument ||
-      currentEvent == Event::kEndDocument) {
+  if (currentEvent == Event::kBadDocument || currentEvent == Event::kEndDocument) {
     return currentEvent;
   }
 
   event_queue_.pop();
   while (event_queue_.empty()) {
-    in_.read(buffer_, sizeof(buffer_) / sizeof(*buffer_));
+    const char* buffer = nullptr;
+    size_t buffer_size = 0;
+    bool done = false;
+    if (!in_->Next(reinterpret_cast<const void**>(&buffer), &buffer_size)) {
+      if (in_->HadError()) {
+        error_ = in_->GetError();
+        event_queue_.push(EventData{Event::kBadDocument});
+        break;
+      }
 
-    const bool done = in_.eof();
-    if (in_.bad() && !done) {
-      error_ = strerror(errno);
-      event_queue_.push(EventData{Event::kBadDocument});
-      continue;
+      done = true;
     }
 
-    if (XML_Parse(parser_, buffer_, in_.gcount(), done) == XML_STATUS_ERROR) {
+    if (XML_Parse(parser_, buffer, buffer_size, done) == XML_STATUS_ERROR) {
       error_ = XML_ErrorString(XML_GetErrorCode(parser_));
       event_queue_.push(EventData{Event::kBadDocument});
-      continue;
+      break;
     }
 
     if (done) {
diff --git a/tools/aapt2/xml/XmlPullParser.h b/tools/aapt2/xml/XmlPullParser.h
index cdeeefd..a00caa1 100644
--- a/tools/aapt2/xml/XmlPullParser.h
+++ b/tools/aapt2/xml/XmlPullParser.h
@@ -31,6 +31,7 @@
 #include "androidfw/StringPiece.h"
 
 #include "Resource.h"
+#include "io/Io.h"
 #include "process/IResourceTableConsumer.h"
 #include "util/Maybe.h"
 #include "xml/XmlUtil.h"
@@ -64,7 +65,7 @@
   static bool SkipCurrentElement(XmlPullParser* parser);
   static bool IsGoodEvent(Event event);
 
-  explicit XmlPullParser(std::istream& in);
+  explicit XmlPullParser(io::InputStream* in);
   ~XmlPullParser();
 
   /**
@@ -169,9 +170,8 @@
     std::vector<Attribute> attributes;
   };
 
-  std::istream& in_;
+  io::InputStream* in_;
   XML_Parser parser_;
-  char buffer_[16384];
   std::queue<EventData> event_queue_;
   std::string error_;
   const std::string empty_;
@@ -228,18 +228,15 @@
   return out;
 }
 
-inline bool XmlPullParser::NextChildNode(XmlPullParser* parser,
-                                         size_t start_depth) {
+inline bool XmlPullParser::NextChildNode(XmlPullParser* parser, size_t start_depth) {
   Event event;
 
   // First get back to the start depth.
-  while (IsGoodEvent(event = parser->Next()) &&
-         parser->depth() > start_depth + 1) {
+  while (IsGoodEvent(event = parser->Next()) && parser->depth() > start_depth + 1) {
   }
 
   // Now look for the first good node.
-  while ((event != Event::kEndElement || parser->depth() > start_depth) &&
-         IsGoodEvent(event)) {
+  while ((event != Event::kEndElement || parser->depth() > start_depth) && IsGoodEvent(event)) {
     switch (event) {
       case Event::kText:
       case Event::kComment:
diff --git a/tools/aapt2/xml/XmlPullParser_test.cpp b/tools/aapt2/xml/XmlPullParser_test.cpp
index 1cce485..681d9d4 100644
--- a/tools/aapt2/xml/XmlPullParser_test.cpp
+++ b/tools/aapt2/xml/XmlPullParser_test.cpp
@@ -16,21 +16,22 @@
 
 #include "xml/XmlPullParser.h"
 
-#include <sstream>
-
 #include "androidfw/StringPiece.h"
 
+#include "io/StringInputStream.h"
 #include "test/Test.h"
 
-using android::StringPiece;
+using ::aapt::io::StringInputStream;
+using ::android::StringPiece;
 
 namespace aapt {
 
 TEST(XmlPullParserTest, NextChildNodeTraversesCorrectly) {
-  std::stringstream str;
-  str << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
-         "<a><b><c xmlns:a=\"http://schema.org\"><d/></c><e/></b></a>";
-  xml::XmlPullParser parser(str);
+  std::string str =
+      R"(<?xml version="1.0" encoding="utf-8"?>
+         <a><b><c xmlns:a="http://schema.org"><d/></c><e/></b></a>)";
+  StringInputStream input(str);
+  xml::XmlPullParser parser(&input);
 
   const size_t depth_outer = parser.depth();
   ASSERT_TRUE(xml::XmlPullParser::NextChildNode(&parser, depth_outer));
diff --git a/tools/aapt2/xml/XmlUtil.h b/tools/aapt2/xml/XmlUtil.h
index 1650ac2..866b6dc 100644
--- a/tools/aapt2/xml/XmlUtil.h
+++ b/tools/aapt2/xml/XmlUtil.h
@@ -26,79 +26,56 @@
 namespace xml {
 
 constexpr const char* kSchemaAuto = "http://schemas.android.com/apk/res-auto";
-constexpr const char* kSchemaPublicPrefix =
-    "http://schemas.android.com/apk/res/";
-constexpr const char* kSchemaPrivatePrefix =
-    "http://schemas.android.com/apk/prv/res/";
-constexpr const char* kSchemaAndroid =
-    "http://schemas.android.com/apk/res/android";
+constexpr const char* kSchemaPublicPrefix = "http://schemas.android.com/apk/res/";
+constexpr const char* kSchemaPrivatePrefix = "http://schemas.android.com/apk/prv/res/";
+constexpr const char* kSchemaAndroid = "http://schemas.android.com/apk/res/android";
 constexpr const char* kSchemaTools = "http://schemas.android.com/tools";
 constexpr const char* kSchemaAapt = "http://schemas.android.com/aapt";
 
-/**
- * Result of extracting a package name from a namespace URI declaration.
- */
+// Result of extracting a package name from a namespace URI declaration.
 struct ExtractedPackage {
-  /**
-   * The name of the package. This can be the empty string, which means that the
-   * package
-   * should be assumed to be the package being compiled.
-   */
+  // The name of the package. This can be the empty string, which means that the package
+  // should be assumed to be the package being compiled.
   std::string package;
 
-  /**
-   * True if the package's private namespace was declared. This means that
-   * private resources
-   * are made visible.
-   */
+  // True if the package's private namespace was declared. This means that private resources
+  // are made visible.
   bool private_namespace;
+
+  friend inline bool operator==(const ExtractedPackage& a, const ExtractedPackage& b) {
+    return a.package == b.package && a.private_namespace == b.private_namespace;
+  }
 };
 
-/**
- * Returns an ExtractedPackage struct if the namespace URI is of the form:
- * http://schemas.android.com/apk/res/<package> or
- * http://schemas.android.com/apk/prv/res/<package>
- *
- * Special case: if namespaceUri is http://schemas.android.com/apk/res-auto,
- * returns an empty package name.
- */
-Maybe<ExtractedPackage> ExtractPackageFromNamespace(
-    const std::string& namespace_uri);
+// Returns an ExtractedPackage struct if the namespace URI is of the form:
+//   http://schemas.android.com/apk/res/<package> or
+//   http://schemas.android.com/apk/prv/res/<package>
+//
+// Special case: if namespaceUri is http://schemas.android.com/apk/res-auto,
+// returns an empty package name.
+Maybe<ExtractedPackage> ExtractPackageFromNamespace(const std::string& namespace_uri);
 
-/**
- * Returns an XML Android namespace for the given package of the form:
- *
- * http://schemas.android.com/apk/res/<package>
- *
- * If privateReference == true, the package will be of the form:
- *
- * http://schemas.android.com/apk/prv/res/<package>
- */
+// Returns an XML Android namespace for the given package of the form:
+//   http://schemas.android.com/apk/res/<package>
+//
+// If privateReference == true, the package will be of the form:
+//   http://schemas.android.com/apk/prv/res/<package>
 std::string BuildPackageNamespace(const android::StringPiece& package,
                                   bool private_reference = false);
 
-/**
- * Interface representing a stack of XML namespace declarations. When looking up
- * the package
- * for a namespace prefix, the stack is checked from top to bottom.
- */
+// Interface representing a stack of XML namespace declarations. When looking up the package
+// for a namespace prefix, the stack is checked from top to bottom.
 struct IPackageDeclStack {
   virtual ~IPackageDeclStack() = default;
 
-  /**
-   * Returns an ExtractedPackage struct if the alias given corresponds with a
-   * package declaration.
-   */
+  // Returns an ExtractedPackage struct if the alias given corresponds with a package declaration.
   virtual Maybe<ExtractedPackage> TransformPackageAlias(
       const android::StringPiece& alias, const android::StringPiece& local_package) const = 0;
 };
 
-/**
- * Helper function for transforming the original Reference inRef to a fully
- * qualified reference
- * via the IPackageDeclStack. This will also mark the Reference as private if
- * the namespace of the package declaration was private.
- */
+// Helper function for transforming the original Reference inRef to a fully qualified reference
+// via the IPackageDeclStack. This will also mark the Reference as private if the namespace of the
+// package declaration was private.
 void TransformReferenceFromNamespace(IPackageDeclStack* decl_stack,
                                      const android::StringPiece& local_package, Reference* in_ref);