Merge "Compile secondary dex files in DexManager"
diff --git a/Android.mk b/Android.mk
index fbcea90..e68b310 100644
--- a/Android.mk
+++ b/Android.mk
@@ -148,6 +148,7 @@
 	core/java/android/content/ISyncContext.aidl \
 	core/java/android/content/ISyncServiceAdapter.aidl \
 	core/java/android/content/ISyncStatusObserver.aidl \
+	core/java/android/content/om/IOverlayManager.aidl \
 	core/java/android/content/pm/ILauncherApps.aidl \
 	core/java/android/content/pm/IOnAppsChangedListener.aidl \
 	core/java/android/content/pm/IOnPermissionsChangeListener.aidl \
@@ -305,6 +306,7 @@
 	core/java/android/service/wallpaper/IWallpaperService.aidl \
 	core/java/android/service/chooser/IChooserTargetService.aidl \
 	core/java/android/service/chooser/IChooserTargetResult.aidl \
+	core/java/android/text/ITextClassificationService.aidl \
 	core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl\
 	core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl\
 	core/java/android/view/accessibility/IAccessibilityManager.aidl \
@@ -464,6 +466,8 @@
         telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl \
         telephony/java/com/android/ims/internal/IImsMultiEndpoint.aidl \
 	telephony/java/com/android/ims/internal/IImsService.aidl \
+	telephony/java/com/android/ims/internal/IImsServiceController.aidl \
+	telephony/java/com/android/ims/internal/IImsServiceFeatureListener.aidl \
 	telephony/java/com/android/ims/internal/IImsStreamMediaSession.aidl \
 	telephony/java/com/android/ims/internal/IImsUt.aidl \
 	telephony/java/com/android/ims/internal/IImsUtListener.aidl \
@@ -1407,6 +1411,8 @@
 # ====  c++ proto host library  ==============================
 include $(CLEAR_VARS)
 LOCAL_MODULE := libplatformprotos
+# b/34740546, work around clang-tidy segmentation fault.
+LOCAL_TIDY_CHECKS := -modernize*
 LOCAL_PROTOC_OPTIMIZE_TYPE := full
 LOCAL_PROTOC_FLAGS := \
     --include_source_info \
diff --git a/api/current.txt b/api/current.txt
index 1228db8..805586e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1119,6 +1119,7 @@
     field public static final int searchSuggestSelection = 16843224; // 0x10101d8
     field public static final int searchSuggestThreshold = 16843373; // 0x101026d
     field public static final int searchViewStyle = 16843904; // 0x1010480
+    field public static final int secondaryContentAlpha = 16843688; // 0x10103a8
     field public static final int secondaryProgress = 16843064; // 0x1010138
     field public static final int secondaryProgressTint = 16843879; // 0x1010467
     field public static final int secondaryProgressTintMode = 16843880; // 0x1010468
@@ -3552,6 +3553,7 @@
     method public android.view.WindowManager getWindowManager();
     method public boolean hasWindowFocus();
     method public void invalidateOptionsMenu();
+    method public boolean isActivityTransitionRunning();
     method public boolean isChangingConfigurations();
     method public final boolean isChild();
     method public boolean isDestroyed();
@@ -5050,6 +5052,7 @@
     field public static final java.lang.String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
     field public static final java.lang.String EXTRA_BIG_TEXT = "android.bigText";
     field public static final java.lang.String EXTRA_CHRONOMETER_COUNT_DOWN = "android.chronometerCountDown";
+    field public static final java.lang.String EXTRA_COLORIZED = "android.colorized";
     field public static final java.lang.String EXTRA_COMPACT_ACTIONS = "android.compactActions";
     field public static final java.lang.String EXTRA_CONVERSATION_TITLE = "android.conversationTitle";
     field public static final java.lang.String EXTRA_HISTORIC_MESSAGES = "android.messages.historic";
@@ -5196,7 +5199,8 @@
   }
 
   public static class Notification.Builder {
-    ctor public Notification.Builder(android.content.Context);
+    ctor public Notification.Builder(android.content.Context, java.lang.String);
+    ctor public deprecated Notification.Builder(android.content.Context);
     method public deprecated android.app.Notification.Builder addAction(int, java.lang.CharSequence, android.app.PendingIntent);
     method public android.app.Notification.Builder addAction(android.app.Notification.Action);
     method public android.app.Notification.Builder addExtras(android.os.Bundle);
@@ -5215,6 +5219,7 @@
     method public android.app.Notification.Builder setChannel(java.lang.String);
     method public android.app.Notification.Builder setChronometerCountDown(boolean);
     method public android.app.Notification.Builder setColor(int);
+    method public android.app.Notification.Builder setColorized(boolean);
     method public deprecated android.app.Notification.Builder setContent(android.widget.RemoteViews);
     method public deprecated android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
     method public android.app.Notification.Builder setContentIntent(android.app.PendingIntent);
@@ -5418,6 +5423,8 @@
     method public boolean canShowBadge();
     method public int describeContents();
     method public void enableVibration(boolean);
+    method public android.media.AudioAttributes getAudioAttributes();
+    method public java.lang.String getGroup();
     method public java.lang.String getId();
     method public int getImportance();
     method public int getLockscreenVisibility();
@@ -5425,11 +5432,12 @@
     method public android.net.Uri getSound();
     method public long[] getVibrationPattern();
     method public void setBypassDnd(boolean);
+    method public void setGroup(java.lang.String);
     method public void setImportance(int);
     method public void setLights(boolean);
     method public void setLockscreenVisibility(int);
     method public void setShowBadge(boolean);
-    method public void setSound(android.net.Uri);
+    method public void setSound(android.net.Uri, android.media.AudioAttributes);
     method public void setVibrationPattern(long[]);
     method public boolean shouldShowLights();
     method public boolean shouldVibrate();
@@ -5438,6 +5446,17 @@
     field public static final java.lang.String DEFAULT_CHANNEL_ID = "miscellaneous";
   }
 
+  public final class NotificationChannelGroup implements android.os.Parcelable {
+    ctor public NotificationChannelGroup(java.lang.String, java.lang.CharSequence);
+    ctor protected NotificationChannelGroup(android.os.Parcel);
+    method public int describeContents();
+    method public java.util.List<android.app.NotificationChannel> getChannels();
+    method public java.lang.String getId();
+    method public java.lang.CharSequence getName();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.NotificationChannelGroup> CREATOR;
+  }
+
   public class NotificationManager {
     method public java.lang.String addAutomaticZenRule(android.app.AutomaticZenRule);
     method public boolean areNotificationsEnabled();
@@ -5445,6 +5464,8 @@
     method public void cancel(java.lang.String, int);
     method public void cancelAll();
     method public void createNotificationChannel(android.app.NotificationChannel);
+    method public void createNotificationChannelGroup(android.app.NotificationChannelGroup);
+    method public void createNotificationChannelGroups(java.util.List<android.app.NotificationChannelGroup>);
     method public void createNotificationChannels(java.util.List<android.app.NotificationChannel>);
     method public void deleteNotificationChannel(java.lang.String);
     method public android.service.notification.StatusBarNotification[] getActiveNotifications();
@@ -6123,6 +6144,7 @@
     method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
     method public void clearProfileOwner(android.content.ComponentName);
     method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
+    method public android.content.Intent createAdminSupportIntent(java.lang.String);
     method public android.os.UserHandle createAndManageUser(android.content.ComponentName, java.lang.String, android.content.ComponentName, android.os.PersistableBundle, int);
     method public void enableSystemApp(android.content.ComponentName, java.lang.String);
     method public int enableSystemApp(android.content.ComponentName, android.content.Intent);
@@ -6353,6 +6375,8 @@
     field public static final int PERMISSION_POLICY_AUTO_DENY = 2; // 0x2
     field public static final int PERMISSION_POLICY_AUTO_GRANT = 1; // 0x1
     field public static final int PERMISSION_POLICY_PROMPT = 0; // 0x0
+    field public static final java.lang.String POLICY_DISABLE_CAMERA = "policy_disable_camera";
+    field public static final java.lang.String POLICY_DISABLE_SCREEN_CAPTURE = "policy_disable_screen_capture";
     field public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2
     field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1
     field public static final int SKIP_SETUP_WIZARD = 1; // 0x1
@@ -6890,6 +6914,7 @@
     method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
     method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
     method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
+    method public boolean isRequestPinAppWidgetSupported();
     method public void notifyAppWidgetViewDataChanged(int[], int);
     method public void notifyAppWidgetViewDataChanged(int, int);
     method public void partiallyUpdateAppWidget(int[], android.widget.RemoteViews);
@@ -9769,6 +9794,7 @@
     field public int theme;
     field public int uiOptions;
     field public int uid;
+    field public java.lang.String volumeUuid;
   }
 
   public static class ApplicationInfo.DisplayNameComparator implements java.util.Comparator {
@@ -9897,7 +9923,8 @@
     method public void startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
     method public void startShortcut(android.content.pm.ShortcutInfo, android.graphics.Rect, android.os.Bundle);
     method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
-    field public static final java.lang.String ACTION_CONFIRM_PIN_ITEM = "android.content.pm.action.CONFIRM_PIN_ITEM";
+    field public static final java.lang.String ACTION_CONFIRM_PIN_APPWIDGET = "android.content.pm.action.CONFIRM_PIN_APPWIDGET";
+    field public static final java.lang.String ACTION_CONFIRM_PIN_SHORTCUT = "android.content.pm.action.CONFIRM_PIN_SHORTCUT";
     field public static final java.lang.String EXTRA_PIN_ITEM_REQUEST = "android.content.pm.extra.PIN_ITEM_REQUEST";
   }
 
@@ -10095,6 +10122,7 @@
     method public abstract boolean addPermission(android.content.pm.PermissionInfo);
     method public abstract boolean addPermissionAsync(android.content.pm.PermissionInfo);
     method public abstract deprecated void addPreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName);
+    method public abstract boolean canRequestPackageInstalls();
     method public abstract java.lang.String[] canonicalToCurrentPackageNames(java.lang.String[]);
     method public abstract int checkPermission(java.lang.String, java.lang.String);
     method public abstract int checkSignatures(java.lang.String, java.lang.String);
@@ -10838,6 +10866,7 @@
     method public int getDimensionPixelSize(int, int);
     method public android.graphics.drawable.Drawable getDrawable(int);
     method public float getFloat(int, float);
+    method public android.graphics.Typeface getFont(int);
     method public float getFraction(int, int, int, float);
     method public int getIndex(int);
     method public int getIndexCount();
@@ -14915,6 +14944,7 @@
     field public static final android.hardware.camera2.CaptureRequest.Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AWB_REGIONS;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_CAPTURE_INTENT;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_EFFECT_MODE;
+    field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Boolean> CONTROL_ENABLE_ZSL;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_MODE;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_POST_RAW_SENSITIVITY_BOOST;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_SCENE_MODE;
@@ -14994,6 +15024,7 @@
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_AWB_STATE;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_CAPTURE_INTENT;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_EFFECT_MODE;
+    field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Boolean> CONTROL_ENABLE_ZSL;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_MODE;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_POST_RAW_SENSITIVITY_BOOST;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_SCENE_MODE;
@@ -15219,6 +15250,7 @@
     field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2
     field public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1; // 0x1
     field public static final int VIRTUAL_DISPLAY_FLAG_SECURE = 4; // 0x4
+    field public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
   }
 
   public static abstract interface DisplayManager.DisplayListener {
@@ -20382,7 +20414,7 @@
     field public static final android.os.Parcelable.Creator<android.media.AudioAttributes> CREATOR;
     field public static final int FLAG_AUDIBILITY_ENFORCED = 1; // 0x1
     field public static final int FLAG_HW_AV_SYNC = 16; // 0x10
-    field public static final int FLAG_LOW_LATENCY = 256; // 0x100
+    field public static final deprecated int FLAG_LOW_LATENCY = 256; // 0x100
     field public static final int USAGE_ALARM = 4; // 0x4
     field public static final int USAGE_ASSISTANCE_ACCESSIBILITY = 11; // 0xb
     field public static final int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12; // 0xc
@@ -20823,6 +20855,7 @@
     method protected deprecated int getNativeFrameCount();
     method public static int getNativeOutputSampleRate(int);
     method public int getNotificationMarkerPosition();
+    method public int getPerformanceMode();
     method public int getPlayState();
     method public int getPlaybackHeadPosition();
     method public android.media.PlaybackParams getPlaybackParams();
@@ -20869,6 +20902,9 @@
     field public static final int ERROR_INVALID_OPERATION = -3; // 0xfffffffd
     field public static final int MODE_STATIC = 0; // 0x0
     field public static final int MODE_STREAM = 1; // 0x1
+    field public static final int PERFORMANCE_MODE_LOW_LATENCY = 1; // 0x1
+    field public static final int PERFORMANCE_MODE_NONE = 0; // 0x0
+    field public static final int PERFORMANCE_MODE_POWER_SAVING = 2; // 0x2
     field public static final int PLAYSTATE_PAUSED = 2; // 0x2
     field public static final int PLAYSTATE_PLAYING = 3; // 0x3
     field public static final int PLAYSTATE_STOPPED = 1; // 0x1
@@ -20886,6 +20922,7 @@
     method public android.media.AudioTrack.Builder setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException;
     method public android.media.AudioTrack.Builder setAudioFormat(android.media.AudioFormat) throws java.lang.IllegalArgumentException;
     method public android.media.AudioTrack.Builder setBufferSizeInBytes(int) throws java.lang.IllegalArgumentException;
+    method public android.media.AudioTrack.Builder setPerformanceMode(int);
     method public android.media.AudioTrack.Builder setSessionId(int) throws java.lang.IllegalArgumentException;
     method public android.media.AudioTrack.Builder setTransferMode(int) throws java.lang.IllegalArgumentException;
   }
@@ -20900,6 +20937,40 @@
     method public default void onRoutingChanged(android.media.AudioRouting);
   }
 
+  public final class BufferingParams implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getInitialBufferingMode();
+    method public int getInitialBufferingWatermarkKB();
+    method public int getInitialBufferingWatermarkMs();
+    method public int getRebufferingMode();
+    method public int getRebufferingWatermarkHighKB();
+    method public int getRebufferingWatermarkHighMs();
+    method public int getRebufferingWatermarkLowKB();
+    method public int getRebufferingWatermarkLowMs();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int BUFFERING_MODE_NONE = 0; // 0x0
+    field public static final int BUFFERING_MODE_SIZE_ONLY = 2; // 0x2
+    field public static final int BUFFERING_MODE_TIME_ONLY = 1; // 0x1
+    field public static final int BUFFERING_MODE_TIME_THEN_SIZE = 3; // 0x3
+    field public static final android.os.Parcelable.Creator<android.media.BufferingParams> CREATOR;
+  }
+
+  public static class BufferingParams.Builder {
+    ctor public BufferingParams.Builder();
+    ctor public BufferingParams.Builder(android.media.BufferingParams);
+    method public android.media.BufferingParams build();
+    method public android.media.BufferingParams.Builder setInitialBufferingMode(int);
+    method public android.media.BufferingParams.Builder setInitialBufferingWatermarkKB(int);
+    method public android.media.BufferingParams.Builder setInitialBufferingWatermarkMs(int);
+    method public android.media.BufferingParams.Builder setRebufferingMode(int);
+    method public android.media.BufferingParams.Builder setRebufferingWatermarkHighKB(int);
+    method public android.media.BufferingParams.Builder setRebufferingWatermarkHighMs(int);
+    method public android.media.BufferingParams.Builder setRebufferingWatermarkLowKB(int);
+    method public android.media.BufferingParams.Builder setRebufferingWatermarkLowMs(int);
+    method public android.media.BufferingParams.Builder setRebufferingWatermarksKB(int, int);
+    method public android.media.BufferingParams.Builder setRebufferingWatermarksMs(int, int);
+  }
+
   public class CamcorderProfile {
     method public static android.media.CamcorderProfile get(int);
     method public static android.media.CamcorderProfile get(int, int);
@@ -21252,6 +21323,7 @@
     method public deprecated java.nio.ByteBuffer[] getInputBuffers();
     method public final android.media.MediaFormat getInputFormat();
     method public android.media.Image getInputImage(int);
+    method public android.os.Bundle getMetrics();
     method public final java.lang.String getName();
     method public java.nio.ByteBuffer getOutputBuffer(int);
     method public deprecated java.nio.ByteBuffer[] getOutputBuffers();
@@ -22044,6 +22116,7 @@
 
   public final class MediaMuxer {
     ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException;
+    ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException;
     method public int addTrack(android.media.MediaFormat);
     method public void release();
     method public void setLocation(float, float);
@@ -22072,8 +22145,14 @@
     method public static android.media.MediaPlayer create(android.content.Context, int, android.media.AudioAttributes, int);
     method public void deselectTrack(int) throws java.lang.IllegalStateException;
     method public int getAudioSessionId();
+    method public android.media.BufferingParams getBufferingParams();
     method public int getCurrentPosition();
+    method public android.media.BufferingParams getDefaultBufferingParams();
+    method public android.media.MediaPlayer.DrmInfo getDrmInfo();
+    method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
     method public int getDuration();
+    method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
+    method public android.os.Bundle getMetrics();
     method public android.media.PlaybackParams getPlaybackParams();
     method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
     method public android.media.SyncParams getSyncParams();
@@ -22086,8 +22165,12 @@
     method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
     method public void prepareAsync() throws java.lang.IllegalStateException;
+    method public void prepareDrm(java.util.UUID, android.media.MediaPlayer.OnDrmConfigCallback) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
+    method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.MediaPlayer.NoDrmSchemeException;
     method public void release();
+    method public void releaseDrm() throws android.media.MediaPlayer.NoDrmSchemeException;
     method public void reset();
+    method public void restoreKeys(byte[]) throws android.media.MediaPlayer.NoDrmSchemeException;
     method public void seekTo(int, int) throws java.lang.IllegalStateException;
     method public void seekTo(int) throws java.lang.IllegalStateException;
     method public void selectTrack(int) throws java.lang.IllegalStateException;
@@ -22095,6 +22178,7 @@
     method public void setAudioSessionId(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public deprecated void setAudioStreamType(int);
     method public void setAuxEffectSendLevel(float);
+    method public void setBufferingParams(android.media.BufferingParams);
     method public void setDataSource(android.content.Context, android.net.Uri) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
     method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
     method public void setDataSource(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
@@ -22103,10 +22187,15 @@
     method public void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public void setDataSource(android.media.MediaDataSource) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public void setDisplay(android.view.SurfaceHolder);
+    method public void setDrmPropertyString(java.lang.String, java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
     method public void setLooping(boolean);
     method public void setNextMediaPlayer(android.media.MediaPlayer);
     method public void setOnBufferingUpdateListener(android.media.MediaPlayer.OnBufferingUpdateListener);
     method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
+    method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener);
+    method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener, android.os.Handler);
+    method public void setOnDrmPreparedListener(android.media.MediaPlayer.OnDrmPreparedListener);
+    method public void setOnDrmPreparedListener(android.media.MediaPlayer.OnDrmPreparedListener, android.os.Handler);
     method public void setOnErrorListener(android.media.MediaPlayer.OnErrorListener);
     method public void setOnInfoListener(android.media.MediaPlayer.OnInfoListener);
     method public void setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener);
@@ -22149,6 +22238,16 @@
     field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = 2; // 0x2
   }
 
+  public static final class MediaPlayer.DrmInfo {
+    method public java.lang.String[] getMimes();
+    method public java.util.Map<java.util.UUID, byte[]> getPssh();
+    method public java.util.UUID[] getSupportedSchemes();
+  }
+
+  public static final class MediaPlayer.NoDrmSchemeException extends android.media.MediaDrmException {
+    ctor public MediaPlayer.NoDrmSchemeException(java.lang.String);
+  }
+
   public static abstract interface MediaPlayer.OnBufferingUpdateListener {
     method public abstract void onBufferingUpdate(android.media.MediaPlayer, int);
   }
@@ -22157,6 +22256,19 @@
     method public abstract void onCompletion(android.media.MediaPlayer);
   }
 
+  public static abstract class MediaPlayer.OnDrmConfigCallback {
+    ctor public MediaPlayer.OnDrmConfigCallback();
+    method public void onDrmConfig(android.media.MediaPlayer);
+  }
+
+  public static abstract interface MediaPlayer.OnDrmInfoListener {
+    method public abstract void onDrmInfo(android.media.MediaPlayer, android.media.MediaPlayer.DrmInfo);
+  }
+
+  public static abstract interface MediaPlayer.OnDrmPreparedListener {
+    method public abstract void onDrmPrepared(android.media.MediaPlayer, boolean);
+  }
+
   public static abstract interface MediaPlayer.OnErrorListener {
     method public abstract boolean onError(android.media.MediaPlayer, int, int);
   }
@@ -22185,6 +22297,10 @@
     method public abstract void onVideoSizeChanged(android.media.MediaPlayer, int, int);
   }
 
+  public static final class MediaPlayer.ProvisioningErrorException extends android.media.MediaDrmException {
+    ctor public MediaPlayer.ProvisioningErrorException(java.lang.String);
+  }
+
   public static class MediaPlayer.TrackInfo implements android.os.Parcelable {
     method public int describeContents();
     method public android.media.MediaFormat getFormat();
@@ -23784,7 +23900,16 @@
   }
 
   public static final class TvContract.Programs implements android.media.tv.TvContract.BaseTvColumns {
+    field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
+    field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
+    field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
+    field public static final java.lang.String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
+    field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
+    field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
+    field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
     field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
+    field public static final java.lang.String COLUMN_AUTHOR = "author";
+    field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
     field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
     field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
     field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
@@ -23793,13 +23918,20 @@
     field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
     field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
     field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+    field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
+    field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
     field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
     field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
     field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
     field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
     field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
     field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
+    field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
+    field public static final java.lang.String COLUMN_LIVE = "live";
+    field public static final java.lang.String COLUMN_LOGO = "logo";
     field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+    field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
+    field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
     field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
     field public static final java.lang.String COLUMN_PREVIEW_DURATION = "preview_duration";
     field public static final java.lang.String COLUMN_PREVIEW_INTENT_URI = "preview_intent_uri";
@@ -23807,20 +23939,52 @@
     field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
     field public static final java.lang.String COLUMN_PREVIEW_WEIGHT = "preview_weight";
     field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
+    field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
+    field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
+    field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
     field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
     field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
     field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number";
     field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
     field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
+    field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
     field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
+    field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
     field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
     field public static final java.lang.String COLUMN_TITLE = "title";
+    field public static final java.lang.String COLUMN_TYPE = "type";
     field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
     field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
     field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
+    field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program";
     field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
+    field public static final java.lang.String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
+    field public static final java.lang.String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
+    field public static final java.lang.String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
+    field public static final java.lang.String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
+    field public static final java.lang.String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
+    field public static final java.lang.String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
+    field public static final java.lang.String REVIEW_RATING_STYLE_PERCENTAGE = "REVIEW_RATING_STYLE_PERCENTAGE";
+    field public static final java.lang.String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
+    field public static final java.lang.String REVIEW_RATING_STYLE_THUMBS_UP_DOWN = "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
+    field public static final java.lang.String TYPE_ALBUM = "TYPE_ALBUM";
+    field public static final java.lang.String TYPE_ARTIST = "TYPE_ARTIST";
+    field public static final java.lang.String TYPE_CHANNEL = "TYPE_CHANNEL";
+    field public static final java.lang.String TYPE_CLIP = "TYPE_CLIP";
+    field public static final java.lang.String TYPE_EVENT = "TYPE_EVENT";
+    field public static final java.lang.String TYPE_MOVIE = "TYPE_MOVIE";
+    field public static final java.lang.String TYPE_PLAYLIST = "TYPE_PLAYLIST";
+    field public static final java.lang.String TYPE_STATION = "TYPE_STATION";
+    field public static final java.lang.String TYPE_TRACK = "TYPE_TRACK";
+    field public static final java.lang.String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
+    field public static final java.lang.String TYPE_TV_SEASON = "TYPE_TV_SEASON";
+    field public static final java.lang.String TYPE_TV_SERIES = "TYPE_TV_SERIES";
+    field public static final java.lang.String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
+    field public static final java.lang.String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
+    field public static final java.lang.String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
   }
 
   public static final class TvContract.Programs.Genres {
@@ -23931,10 +24095,13 @@
     method public void unregisterCallback(android.media.tv.TvInputManager.TvInputCallback);
     method public void updateTvInputInfo(android.media.tv.TvInputInfo);
     field public static final java.lang.String ACTION_BLOCKED_RATINGS_CHANGED = "android.media.tv.action.BLOCKED_RATINGS_CHANGED";
+    field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
     field public static final java.lang.String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED = "android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED";
     field public static final java.lang.String ACTION_QUERY_CONTENT_RATING_SYSTEMS = "android.media.tv.action.QUERY_CONTENT_RATING_SYSTEMS";
     field public static final java.lang.String ACTION_SETUP_INPUTS = "android.media.tv.action.SETUP_INPUTS";
     field public static final java.lang.String ACTION_VIEW_RECORDING_SCHEDULES = "android.media.tv.action.VIEW_RECORDING_SCHEDULES";
+    field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
+    field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
     field public static final int INPUT_STATE_CONNECTED = 0; // 0x0
     field public static final int INPUT_STATE_CONNECTED_STANDBY = 1; // 0x1
     field public static final int INPUT_STATE_DISCONNECTED = 2; // 0x2
@@ -25463,6 +25630,7 @@
     method public java.security.cert.X509Certificate getCaCertificate();
     method public java.security.cert.X509Certificate[] getCaCertificates();
     method public java.security.cert.X509Certificate getClientCertificate();
+    method public java.security.cert.X509Certificate[] getClientCertificateChain();
     method public java.lang.String getDomainSuffixMatch();
     method public int getEapMethod();
     method public java.lang.String getIdentity();
@@ -25476,6 +25644,7 @@
     method public void setCaCertificate(java.security.cert.X509Certificate);
     method public void setCaCertificates(java.security.cert.X509Certificate[]);
     method public void setClientKeyEntry(java.security.PrivateKey, java.security.cert.X509Certificate);
+    method public void setClientKeyEntryWithCertificateChain(java.security.PrivateKey, java.security.cert.X509Certificate[]);
     method public void setDomainSuffixMatch(java.lang.String);
     method public void setEapMethod(int);
     method public void setIdentity(java.lang.String);
@@ -25551,6 +25720,7 @@
     method public boolean isTdlsSupported();
     method public boolean isWifiEnabled();
     method public boolean pingSupplicant();
+    method public void queryPasspointIcon(long, java.lang.String);
     method public boolean reassociate();
     method public boolean reconnect();
     method public boolean removeNetwork(int);
@@ -25561,6 +25731,10 @@
     method public boolean startScan();
     method public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsCallback);
     method public int updateNetwork(android.net.wifi.WifiConfiguration);
+    field public static final java.lang.String ACTION_PASSPOINT_DEAUTH_IMMINENT = "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT";
+    field public static final java.lang.String ACTION_PASSPOINT_ICON = "android.net.wifi.action.PASSPOINT_ICON";
+    field public static final java.lang.String ACTION_PASSPOINT_OSU_PROVIDERS_LIST = "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST";
+    field public static final java.lang.String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION = "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION";
     field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
     field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
     field public static final int ERROR_AUTHENTICATING = 1; // 0x1
@@ -25568,6 +25742,18 @@
     field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
     field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi";
     field public static final java.lang.String EXTRA_NEW_STATE = "newState";
+    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_BSSID = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_BSSID";
+    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_ESS = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_ESS";
+    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REASON_URL = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REASON_URL";
+    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY";
+    field public static final java.lang.String EXTRA_PASSPOINT_ICON_BSSID = "android.net.wifi.extra.PASSPOINT_ICON_BSSID";
+    field public static final java.lang.String EXTRA_PASSPOINT_ICON_DATA = "android.net.wifi.extra.PASSPOINT_ICON_DATA";
+    field public static final java.lang.String EXTRA_PASSPOINT_ICON_FILENAME = "android.net.wifi.extra.PASSPOINT_ICON_FILENAME";
+    field public static final java.lang.String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_BSSID = "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_BSSID";
+    field public static final java.lang.String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_DATA = "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_DATA";
+    field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID";
+    field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD";
+    field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL";
     field public static final java.lang.String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
     field public static final java.lang.String EXTRA_RESULTS_UPDATED = "resultsUpdated";
     field public static final java.lang.String EXTRA_SUPPLICANT_CONNECTED = "connected";
@@ -33531,6 +33717,7 @@
     field public static final java.lang.String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
     field public static final java.lang.String ACTION_MANAGE_APPLICATIONS_SETTINGS = "android.settings.MANAGE_APPLICATIONS_SETTINGS";
     field public static final java.lang.String ACTION_MANAGE_DEFAULT_APPS_SETTINGS = "android.settings.MANAGE_DEFAULT_APPS_SETTINGS";
+    field public static final java.lang.String ACTION_MANAGE_EXTERNAL_SOURCES = "android.settings.action.MANAGE_EXTERNAL_SOURCES";
     field public static final java.lang.String ACTION_MANAGE_OVERLAY_PERMISSION = "android.settings.action.MANAGE_OVERLAY_PERMISSION";
     field public static final java.lang.String ACTION_MANAGE_WRITE_SETTINGS = "android.settings.action.MANAGE_WRITE_SETTINGS";
     field public static final java.lang.String ACTION_MEMORY_CARD_SETTINGS = "android.settings.MEMORY_CARD_SETTINGS";
@@ -33678,7 +33865,7 @@
     field public static final java.lang.String ENABLED_INPUT_METHODS = "enabled_input_methods";
     field public static final deprecated java.lang.String HTTP_PROXY = "http_proxy";
     field public static final java.lang.String INPUT_METHOD_SELECTOR_VISIBILITY = "input_method_selector_visibility";
-    field public static final java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
+    field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
     field public static final java.lang.String LOCATION_MODE = "location_mode";
     field public static final int LOCATION_MODE_BATTERY_SAVING = 2; // 0x2
     field public static final int LOCATION_MODE_HIGH_ACCURACY = 3; // 0x3
@@ -34233,6 +34420,8 @@
 
   public static final class VoicemailContract.Voicemails implements android.provider.BaseColumns android.provider.OpenableColumns {
     method public static android.net.Uri buildSourceUri(java.lang.String);
+    field public static final java.lang.String ARCHIVED = "archived";
+    field public static final java.lang.String BACKED_UP = "backed_up";
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String DATE = "date";
     field public static final java.lang.String DELETED = "deleted";
@@ -34240,6 +34429,7 @@
     field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemails";
     field public static final java.lang.String DURATION = "duration";
     field public static final java.lang.String HAS_CONTENT = "has_content";
+    field public static final java.lang.String IS_OMTP_VOICEMAIL = "is_omtp_voicemail";
     field public static final java.lang.String IS_READ = "is_read";
     field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail";
     field public static final java.lang.String LAST_MODIFIED = "last_modified";
@@ -34247,6 +34437,7 @@
     field public static final java.lang.String NUMBER = "number";
     field public static final java.lang.String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name";
     field public static final java.lang.String PHONE_ACCOUNT_ID = "subscription_id";
+    field public static final java.lang.String RESTORED = "restored";
     field public static final java.lang.String SOURCE_DATA = "source_data";
     field public static final java.lang.String SOURCE_PACKAGE = "source_package";
     field public static final java.lang.String TRANSCRIPTION = "transcription";
@@ -35624,17 +35815,25 @@
     ctor public AutoFillService();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConnected();
+    method public void onDatasetAuthenticationRequest(android.os.Bundle, int);
     method public void onDisconnected();
     method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback);
-    method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.SaveCallback);
+    method public void onFillResponseAuthenticationRequest(android.os.Bundle, int);
+    method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
     field public static final java.lang.String EXTRA_DATASET_EXTRAS = "android.service.autofill.extra.DATASET_EXTRAS";
     field public static final java.lang.String EXTRA_RESPONSE_EXTRAS = "android.service.autofill.extra.RESPONSE_EXTRAS";
+    field public static final int FLAG_AUTHENTICATION_ERROR = 4; // 0x4
+    field public static final int FLAG_AUTHENTICATION_REQUESTED = 1; // 0x1
+    field public static final int FLAG_AUTHENTICATION_SUCCESS = 2; // 0x2
+    field public static final int FLAG_FINGERPRINT_AUTHENTICATION_NOT_AVAILABLE = 8; // 0x8
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
     field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
   }
 
   public final class FillCallback {
+    method public void onDatasetAuthentication(android.view.autofill.Dataset, int);
     method public void onFailure(java.lang.CharSequence);
+    method public void onFillResponseAuthentication(int);
     method public void onSuccess(android.view.autofill.FillResponse);
   }
 
@@ -38064,6 +38263,7 @@
     field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING = "ci_action_on_sys_update_extra_string";
     field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING = "ci_action_on_sys_update_extra_val_string";
     field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING = "ci_action_on_sys_update_intent_string";
+    field public static final java.lang.String KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING = "config_ims_package_override_string";
     field public static final java.lang.String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool";
     field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
     field public static final java.lang.String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string";
@@ -38679,6 +38879,7 @@
     method public int getSimState();
     method public int getSimState(int);
     method public java.lang.String getSubscriberId();
+    method public java.lang.String getVisualVoicemailPackageName(android.telecom.PhoneAccountHandle);
     method public java.lang.String getVoiceMailAlphaTag();
     method public java.lang.String getVoiceMailNumber();
     method public int getVoiceNetworkType();
@@ -38699,6 +38900,7 @@
     method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
     method public boolean isWorldPhone();
     method public void listen(android.telephony.PhoneStateListener, int);
+    method public boolean sendDialerCode(java.lang.String);
     method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
     method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
     method public void sendUssdRequest(java.lang.String, int, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
@@ -38731,6 +38933,7 @@
     field public static final int DATA_DISCONNECTED = 0; // 0x0
     field public static final int DATA_SUSPENDED = 3; // 0x3
     field public static final java.lang.String EXTRA_CALL_VOICEMAIL_INTENT = "android.telephony.extra.CALL_VOICEMAIL_INTENT";
+    field public static final java.lang.String EXTRA_HIDE_PUBLIC_SETTINGS = "android.telephony.extra.HIDE_PUBLIC_SETTINGS";
     field public static final java.lang.String EXTRA_INCOMING_NUMBER = "incoming_number";
     field public static final java.lang.String EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT = "android.telephony.extra.LAUNCH_VOICEMAIL_SETTINGS_INTENT";
     field public static final java.lang.String EXTRA_NOTIFICATION_COUNT = "android.telephony.extra.NOTIFICATION_COUNT";
@@ -38739,6 +38942,7 @@
     field public static final java.lang.String EXTRA_STATE_OFFHOOK;
     field public static final java.lang.String EXTRA_STATE_RINGING;
     field public static final java.lang.String EXTRA_VOICEMAIL_NUMBER = "android.telephony.extra.VOICEMAIL_NUMBER";
+    field public static final java.lang.String METADATA_HIDE_VOICEMAIL_SETTINGS_MENU = "android.telephony.HIDE_VOICEMAIL_SETTINGS_MENU";
     field public static final int NETWORK_TYPE_1xRTT = 7; // 0x7
     field public static final int NETWORK_TYPE_CDMA = 4; // 0x4
     field public static final int NETWORK_TYPE_EDGE = 2; // 0x2
@@ -39432,6 +39636,7 @@
     method public boolean addPermission(android.content.pm.PermissionInfo);
     method public boolean addPermissionAsync(android.content.pm.PermissionInfo);
     method public void addPreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName);
+    method public boolean canRequestPackageInstalls();
     method public java.lang.String[] canonicalToCurrentPackageNames(java.lang.String[]);
     method public int checkPermission(java.lang.String, java.lang.String);
     method public int checkSignatures(java.lang.String, java.lang.String);
@@ -42417,6 +42622,7 @@
     field public static final int FLAG_PRIVATE = 4; // 0x4
     field public static final int FLAG_ROUND = 16; // 0x10
     field public static final int FLAG_SECURE = 2; // 0x2
+    field public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
     field public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1; // 0x1
     field public static final int INVALID_DISPLAY = -1; // 0xffffffff
     field public static final int STATE_DOZE = 3; // 0x3
@@ -42663,6 +42869,7 @@
     field public static final int SOURCE_JOYSTICK = 16777232; // 0x1000010
     field public static final int SOURCE_KEYBOARD = 257; // 0x101
     field public static final int SOURCE_MOUSE = 8194; // 0x2002
+    field public static final int SOURCE_MOUSE_RELATIVE = 131076; // 0x20004
     field public static final int SOURCE_STYLUS = 16386; // 0x4002
     field public static final int SOURCE_TOUCHPAD = 1048584; // 0x100008
     field public static final int SOURCE_TOUCHSCREEN = 4098; // 0x1002
@@ -43817,6 +44024,7 @@
     method public void createContextMenu(android.view.ContextMenu);
     method public void destroyDrawingCache();
     method public android.view.WindowInsets dispatchApplyWindowInsets(android.view.WindowInsets);
+    method public boolean dispatchCapturedPointerEvent(android.view.MotionEvent);
     method public void dispatchConfigurationChanged(android.content.res.Configuration);
     method public void dispatchDisplayHint(int);
     method public boolean dispatchDragEvent(android.view.DragEvent);
@@ -43835,6 +44043,7 @@
     method public boolean dispatchNestedPrePerformAccessibilityAction(int, android.os.Bundle);
     method public boolean dispatchNestedPreScroll(int, int, int[], int[]);
     method public boolean dispatchNestedScroll(int, int, int, int, int[]);
+    method public void dispatchPointerCaptureChanged(boolean);
     method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public void dispatchProvideAutoFillStructure(android.view.ViewStructure, int);
     method public void dispatchProvideStructure(android.view.ViewStructure);
@@ -43986,7 +44195,6 @@
     method public java.lang.Object getTag(int);
     method public int getTextAlignment();
     method public int getTextDirection();
-    method public final deprecated java.lang.CharSequence getTooltip();
     method public final java.lang.CharSequence getTooltipText();
     method public final int getTop();
     method protected float getTopFadingEdgeStrength();
@@ -44017,6 +44225,7 @@
     method public boolean hasNestedScrollingParent();
     method public boolean hasOnClickListeners();
     method public boolean hasOverlappingRendering();
+    method public boolean hasPointerCapture();
     method public boolean hasTransientState();
     method public boolean hasWindowFocus();
     method public static android.view.View inflate(android.content.Context, int, android.view.ViewGroup);
@@ -44081,6 +44290,7 @@
     method public android.view.WindowInsets onApplyWindowInsets(android.view.WindowInsets);
     method protected void onAttachedToWindow();
     method public void onCancelPendingInputEvents();
+    method public boolean onCapturedPointerEvent(android.view.MotionEvent);
     method public boolean onCheckIsTextEditor();
     method protected void onConfigurationChanged(android.content.res.Configuration);
     method protected void onCreateContextMenu(android.view.ContextMenu);
@@ -44110,6 +44320,7 @@
     method protected void onLayout(boolean, int, int, int, int);
     method protected void onMeasure(int, int);
     method protected void onOverScrolled(int, int, boolean, boolean);
+    method public void onPointerCaptureChange(boolean);
     method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public void onProvideAutoFillStructure(android.view.ViewStructure, int);
     method public void onProvideAutoFillVirtualStructure(android.view.ViewStructure, int);
@@ -44152,6 +44363,7 @@
     method public void postOnAnimation(java.lang.Runnable);
     method public void postOnAnimationDelayed(java.lang.Runnable, long);
     method public void refreshDrawableState();
+    method public void releasePointerCapture();
     method public boolean removeCallbacks(java.lang.Runnable);
     method public void removeOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
     method public void removeOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
@@ -44162,6 +44374,7 @@
     method public boolean requestFocus(int, android.graphics.Rect);
     method public final boolean requestFocusFromTouch();
     method public void requestLayout();
+    method public void requestPointerCapture();
     method public boolean requestRectangleOnScreen(android.graphics.Rect);
     method public boolean requestRectangleOnScreen(android.graphics.Rect, boolean);
     method public final void requestUnbufferedDispatch(android.view.MotionEvent);
@@ -44239,6 +44452,7 @@
     method public void setNextFocusRightId(int);
     method public void setNextFocusUpId(int);
     method public void setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener);
+    method public void setOnCapturedPointerListener(android.view.View.OnCapturedPointerListener);
     method public void setOnClickListener(android.view.View.OnClickListener);
     method public void setOnContextClickListener(android.view.View.OnContextClickListener);
     method public void setOnCreateContextMenuListener(android.view.View.OnCreateContextMenuListener);
@@ -44286,7 +44500,6 @@
     method public void setTag(int, java.lang.Object);
     method public void setTextAlignment(int);
     method public void setTextDirection(int);
-    method public final deprecated void setTooltip(java.lang.CharSequence);
     method public final void setTooltipText(java.lang.CharSequence);
     method public final void setTop(int);
     method public void setTouchDelegate(android.view.TouchDelegate);
@@ -44322,8 +44535,8 @@
     field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
     field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
     field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
-    field public static final int AUTO_FILL_FLAG_TYPE_FILL = 1; // 0x1
-    field public static final int AUTO_FILL_FLAG_TYPE_SAVE = 2; // 0x2
+    field public static final int AUTO_FILL_FLAG_TYPE_FILL = 268435456; // 0x10000000
+    field public static final int AUTO_FILL_FLAG_TYPE_SAVE = 536870912; // 0x20000000
     field public static final int DRAG_FLAG_GLOBAL = 256; // 0x100
     field public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION = 64; // 0x40
     field public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION = 128; // 0x80
@@ -44512,6 +44725,10 @@
     method public abstract void onViewDetachedFromWindow(android.view.View);
   }
 
+  public static abstract interface View.OnCapturedPointerListener {
+    method public abstract boolean onCapturedPointer(android.view.View, android.view.MotionEvent);
+  }
+
   public static abstract interface View.OnClickListener {
     method public abstract void onClick(android.view.View);
   }
@@ -45244,6 +45461,7 @@
     method public abstract boolean onMenuItemSelected(int, android.view.MenuItem);
     method public abstract boolean onMenuOpened(int, android.view.Menu);
     method public abstract void onPanelClosed(int, android.view.Menu);
+    method public default void onPointerCaptureChanged(boolean);
     method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
     method public default void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu, int);
     method public abstract boolean onSearchRequested();
@@ -46251,6 +46469,8 @@
   public static final class Dataset.Builder {
     ctor public Dataset.Builder(java.lang.CharSequence);
     method public android.view.autofill.Dataset build();
+    method public android.view.autofill.Dataset.Builder requiresCustomAuthentication(android.os.Bundle, int);
+    method public android.view.autofill.Dataset.Builder requiresFingerprintAuthentication(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.Bundle, int);
     method public android.view.autofill.Dataset.Builder setExtras(android.os.Bundle);
     method public android.view.autofill.Dataset.Builder setValue(android.view.autofill.AutoFillId, android.view.autofill.AutoFillValue);
   }
@@ -46266,6 +46486,8 @@
     method public android.view.autofill.FillResponse.Builder addDataset(android.view.autofill.Dataset);
     method public android.view.autofill.FillResponse.Builder addSavableFields(android.view.autofill.AutoFillId...);
     method public android.view.autofill.FillResponse build();
+    method public android.view.autofill.FillResponse.Builder requiresCustomAuthentication(android.os.Bundle, int);
+    method public android.view.autofill.FillResponse.Builder requiresFingerprintAuthentication(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.Bundle, int);
     method public android.view.autofill.FillResponse.Builder setExtras(android.os.Bundle);
   }
 
@@ -49054,6 +49276,7 @@
     method public android.graphics.PorterDuff.Mode getSecondaryProgressTintMode();
     method public final synchronized void incrementProgressBy(int);
     method public final synchronized void incrementSecondaryProgressBy(int);
+    method public boolean isAnimating();
     method public synchronized boolean isIndeterminate();
     method public void onRestoreInstanceState(android.os.Parcelable);
     method public android.os.Parcelable onSaveInstanceState();
diff --git a/api/system-current.txt b/api/system-current.txt
index 4698a68..64e9571 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -37,6 +37,7 @@
     field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN";
     field public static final java.lang.String BIND_DIRECTORY_SEARCH = "android.permission.BIND_DIRECTORY_SEARCH";
     field public static final java.lang.String BIND_DREAM_SERVICE = "android.permission.BIND_DREAM_SERVICE";
+    field public static final java.lang.String BIND_IMS_SERVICE = "android.permission.BIND_IMS_SERVICE";
     field public static final java.lang.String BIND_INCALL_SERVICE = "android.permission.BIND_INCALL_SERVICE";
     field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
     field public static final java.lang.String BIND_KEYGUARD_APPWIDGET = "android.permission.BIND_KEYGUARD_APPWIDGET";
@@ -1234,6 +1235,7 @@
     field public static final int searchSuggestSelection = 16843224; // 0x10101d8
     field public static final int searchSuggestThreshold = 16843373; // 0x101026d
     field public static final int searchViewStyle = 16843904; // 0x1010480
+    field public static final int secondaryContentAlpha = 16843688; // 0x10103a8
     field public static final int secondaryProgress = 16843064; // 0x1010138
     field public static final int secondaryProgressTint = 16843879; // 0x1010467
     field public static final int secondaryProgressTintMode = 16843880; // 0x1010468
@@ -3673,6 +3675,7 @@
     method public android.view.WindowManager getWindowManager();
     method public boolean hasWindowFocus();
     method public void invalidateOptionsMenu();
+    method public boolean isActivityTransitionRunning();
     method public boolean isBackgroundVisibleBehind();
     method public boolean isChangingConfigurations();
     method public final boolean isChild();
@@ -5210,6 +5213,7 @@
     field public static final java.lang.String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
     field public static final java.lang.String EXTRA_BIG_TEXT = "android.bigText";
     field public static final java.lang.String EXTRA_CHRONOMETER_COUNT_DOWN = "android.chronometerCountDown";
+    field public static final java.lang.String EXTRA_COLORIZED = "android.colorized";
     field public static final java.lang.String EXTRA_COMPACT_ACTIONS = "android.compactActions";
     field public static final java.lang.String EXTRA_CONVERSATION_TITLE = "android.conversationTitle";
     field public static final java.lang.String EXTRA_HISTORIC_MESSAGES = "android.messages.historic";
@@ -5358,7 +5362,8 @@
   }
 
   public static class Notification.Builder {
-    ctor public Notification.Builder(android.content.Context);
+    ctor public Notification.Builder(android.content.Context, java.lang.String);
+    ctor public deprecated Notification.Builder(android.content.Context);
     method public deprecated android.app.Notification.Builder addAction(int, java.lang.CharSequence, android.app.PendingIntent);
     method public android.app.Notification.Builder addAction(android.app.Notification.Action);
     method public android.app.Notification.Builder addExtras(android.os.Bundle);
@@ -5377,6 +5382,7 @@
     method public android.app.Notification.Builder setChannel(java.lang.String);
     method public android.app.Notification.Builder setChronometerCountDown(boolean);
     method public android.app.Notification.Builder setColor(int);
+    method public android.app.Notification.Builder setColorized(boolean);
     method public deprecated android.app.Notification.Builder setContent(android.widget.RemoteViews);
     method public deprecated android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
     method public android.app.Notification.Builder setContentIntent(android.app.PendingIntent);
@@ -5593,6 +5599,8 @@
     method public boolean canShowBadge();
     method public int describeContents();
     method public void enableVibration(boolean);
+    method public android.media.AudioAttributes getAudioAttributes();
+    method public java.lang.String getGroup();
     method public java.lang.String getId();
     method public int getImportance();
     method public int getLockscreenVisibility();
@@ -5605,11 +5613,12 @@
     method public void populateFromXml(org.xmlpull.v1.XmlPullParser);
     method public void setBypassDnd(boolean);
     method public void setDeleted(boolean);
+    method public void setGroup(java.lang.String);
     method public void setImportance(int);
     method public void setLights(boolean);
     method public void setLockscreenVisibility(int);
     method public void setShowBadge(boolean);
-    method public void setSound(android.net.Uri);
+    method public void setSound(android.net.Uri, android.media.AudioAttributes);
     method public void setVibrationPattern(long[]);
     method public boolean shouldShowLights();
     method public boolean shouldVibrate();
@@ -5620,6 +5629,7 @@
     field public static final java.lang.String DEFAULT_CHANNEL_ID = "miscellaneous";
     field public static final int[] LOCKABLE_FIELDS;
     field public static final int USER_LOCKED_ALLOWED = 64; // 0x40
+    field public static final int USER_LOCKED_AUDIO_ATTRIBUTES = 256; // 0x100
     field public static final int USER_LOCKED_IMPORTANCE = 4; // 0x4
     field public static final int USER_LOCKED_LIGHTS = 8; // 0x8
     field public static final int USER_LOCKED_PRIORITY = 1; // 0x1
@@ -5629,6 +5639,20 @@
     field public static final int USER_LOCKED_VISIBILITY = 2; // 0x2
   }
 
+  public final class NotificationChannelGroup implements android.os.Parcelable {
+    ctor public NotificationChannelGroup(java.lang.String, java.lang.CharSequence);
+    ctor protected NotificationChannelGroup(android.os.Parcel);
+    method public void addChannel(android.app.NotificationChannel);
+    method public int describeContents();
+    method public java.util.List<android.app.NotificationChannel> getChannels();
+    method public java.lang.String getId();
+    method public java.lang.CharSequence getName();
+    method public org.json.JSONObject toJson() throws org.json.JSONException;
+    method public void writeToParcel(android.os.Parcel, int);
+    method public void writeXml(org.xmlpull.v1.XmlSerializer) throws java.io.IOException;
+    field public static final android.os.Parcelable.Creator<android.app.NotificationChannelGroup> CREATOR;
+  }
+
   public class NotificationManager {
     method public java.lang.String addAutomaticZenRule(android.app.AutomaticZenRule);
     method public boolean areNotificationsEnabled();
@@ -5636,6 +5660,8 @@
     method public void cancel(java.lang.String, int);
     method public void cancelAll();
     method public void createNotificationChannel(android.app.NotificationChannel);
+    method public void createNotificationChannelGroup(android.app.NotificationChannelGroup);
+    method public void createNotificationChannelGroups(java.util.List<android.app.NotificationChannelGroup>);
     method public void createNotificationChannels(java.util.List<android.app.NotificationChannel>);
     method public void deleteNotificationChannel(java.lang.String);
     method public android.service.notification.StatusBarNotification[] getActiveNotifications();
@@ -6319,6 +6345,7 @@
     method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
     method public void clearProfileOwner(android.content.ComponentName);
     method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
+    method public android.content.Intent createAdminSupportIntent(java.lang.String);
     method public android.os.UserHandle createAndManageUser(android.content.ComponentName, java.lang.String, android.content.ComponentName, android.os.PersistableBundle, int);
     method public void enableSystemApp(android.content.ComponentName, java.lang.String);
     method public int enableSystemApp(android.content.ComponentName, android.content.Intent);
@@ -6576,6 +6603,8 @@
     field public static final int PERMISSION_POLICY_AUTO_DENY = 2; // 0x2
     field public static final int PERMISSION_POLICY_AUTO_GRANT = 1; // 0x1
     field public static final int PERMISSION_POLICY_PROMPT = 0; // 0x0
+    field public static final java.lang.String POLICY_DISABLE_CAMERA = "policy_disable_camera";
+    field public static final java.lang.String POLICY_DISABLE_SCREEN_CAPTURE = "policy_disable_screen_capture";
     field public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2
     field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1
     field public static final int SKIP_SETUP_WIZARD = 1; // 0x1
@@ -7241,6 +7270,7 @@
     method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
     method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
     method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
+    method public boolean isRequestPinAppWidgetSupported();
     method public void notifyAppWidgetViewDataChanged(int[], int);
     method public void notifyAppWidgetViewDataChanged(int, int);
     method public void partiallyUpdateAppWidget(int[], android.widget.RemoteViews);
@@ -10184,6 +10214,7 @@
     field public int theme;
     field public int uiOptions;
     field public int uid;
+    field public java.lang.String volumeUuid;
   }
 
   public static class ApplicationInfo.DisplayNameComparator implements java.util.Comparator {
@@ -10356,7 +10387,8 @@
     method public void startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
     method public void startShortcut(android.content.pm.ShortcutInfo, android.graphics.Rect, android.os.Bundle);
     method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
-    field public static final java.lang.String ACTION_CONFIRM_PIN_ITEM = "android.content.pm.action.CONFIRM_PIN_ITEM";
+    field public static final java.lang.String ACTION_CONFIRM_PIN_APPWIDGET = "android.content.pm.action.CONFIRM_PIN_APPWIDGET";
+    field public static final java.lang.String ACTION_CONFIRM_PIN_SHORTCUT = "android.content.pm.action.CONFIRM_PIN_SHORTCUT";
     field public static final java.lang.String EXTRA_PIN_ITEM_REQUEST = "android.content.pm.extra.PIN_ITEM_REQUEST";
   }
 
@@ -10560,6 +10592,7 @@
     method public abstract boolean addPermission(android.content.pm.PermissionInfo);
     method public abstract boolean addPermissionAsync(android.content.pm.PermissionInfo);
     method public abstract deprecated void addPreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName);
+    method public abstract boolean canRequestPackageInstalls();
     method public abstract java.lang.String[] canonicalToCurrentPackageNames(java.lang.String[]);
     method public abstract int checkPermission(java.lang.String, java.lang.String);
     method public abstract int checkSignatures(java.lang.String, java.lang.String);
@@ -11396,6 +11429,7 @@
     method public int getDimensionPixelSize(int, int);
     method public android.graphics.drawable.Drawable getDrawable(int);
     method public float getFloat(int, float);
+    method public android.graphics.Typeface getFont(int);
     method public float getFraction(int, int, int, float);
     method public int getIndex(int);
     method public int getIndexCount();
@@ -15481,6 +15515,7 @@
     field public static final android.hardware.camera2.CaptureRequest.Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AWB_REGIONS;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_CAPTURE_INTENT;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_EFFECT_MODE;
+    field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Boolean> CONTROL_ENABLE_ZSL;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_MODE;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_POST_RAW_SENSITIVITY_BOOST;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_SCENE_MODE;
@@ -15560,6 +15595,7 @@
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_AWB_STATE;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_CAPTURE_INTENT;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_EFFECT_MODE;
+    field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Boolean> CONTROL_ENABLE_ZSL;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_MODE;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_POST_RAW_SENSITIVITY_BOOST;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_SCENE_MODE;
@@ -15792,6 +15828,7 @@
     field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2
     field public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1; // 0x1
     field public static final int VIRTUAL_DISPLAY_FLAG_SECURE = 4; // 0x4
+    field public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
   }
 
   public static abstract interface DisplayManager.DisplayListener {
@@ -21937,7 +21974,7 @@
     field public static final int FLAG_BYPASS_MUTE = 128; // 0x80
     field public static final int FLAG_HW_AV_SYNC = 16; // 0x10
     field public static final int FLAG_HW_HOTWORD = 32; // 0x20
-    field public static final int FLAG_LOW_LATENCY = 256; // 0x100
+    field public static final deprecated int FLAG_LOW_LATENCY = 256; // 0x100
     field public static final int USAGE_ALARM = 4; // 0x4
     field public static final int USAGE_ASSISTANCE_ACCESSIBILITY = 11; // 0xb
     field public static final int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12; // 0xc
@@ -22423,6 +22460,7 @@
     method protected deprecated int getNativeFrameCount();
     method public static int getNativeOutputSampleRate(int);
     method public int getNotificationMarkerPosition();
+    method public int getPerformanceMode();
     method public int getPlayState();
     method public int getPlaybackHeadPosition();
     method public android.media.PlaybackParams getPlaybackParams();
@@ -22469,6 +22507,9 @@
     field public static final int ERROR_INVALID_OPERATION = -3; // 0xfffffffd
     field public static final int MODE_STATIC = 0; // 0x0
     field public static final int MODE_STREAM = 1; // 0x1
+    field public static final int PERFORMANCE_MODE_LOW_LATENCY = 1; // 0x1
+    field public static final int PERFORMANCE_MODE_NONE = 0; // 0x0
+    field public static final int PERFORMANCE_MODE_POWER_SAVING = 2; // 0x2
     field public static final int PLAYSTATE_PAUSED = 2; // 0x2
     field public static final int PLAYSTATE_PLAYING = 3; // 0x3
     field public static final int PLAYSTATE_STOPPED = 1; // 0x1
@@ -22486,6 +22527,7 @@
     method public android.media.AudioTrack.Builder setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException;
     method public android.media.AudioTrack.Builder setAudioFormat(android.media.AudioFormat) throws java.lang.IllegalArgumentException;
     method public android.media.AudioTrack.Builder setBufferSizeInBytes(int) throws java.lang.IllegalArgumentException;
+    method public android.media.AudioTrack.Builder setPerformanceMode(int);
     method public android.media.AudioTrack.Builder setSessionId(int) throws java.lang.IllegalArgumentException;
     method public android.media.AudioTrack.Builder setTransferMode(int) throws java.lang.IllegalArgumentException;
   }
@@ -22500,6 +22542,40 @@
     method public default void onRoutingChanged(android.media.AudioRouting);
   }
 
+  public final class BufferingParams implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getInitialBufferingMode();
+    method public int getInitialBufferingWatermarkKB();
+    method public int getInitialBufferingWatermarkMs();
+    method public int getRebufferingMode();
+    method public int getRebufferingWatermarkHighKB();
+    method public int getRebufferingWatermarkHighMs();
+    method public int getRebufferingWatermarkLowKB();
+    method public int getRebufferingWatermarkLowMs();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int BUFFERING_MODE_NONE = 0; // 0x0
+    field public static final int BUFFERING_MODE_SIZE_ONLY = 2; // 0x2
+    field public static final int BUFFERING_MODE_TIME_ONLY = 1; // 0x1
+    field public static final int BUFFERING_MODE_TIME_THEN_SIZE = 3; // 0x3
+    field public static final android.os.Parcelable.Creator<android.media.BufferingParams> CREATOR;
+  }
+
+  public static class BufferingParams.Builder {
+    ctor public BufferingParams.Builder();
+    ctor public BufferingParams.Builder(android.media.BufferingParams);
+    method public android.media.BufferingParams build();
+    method public android.media.BufferingParams.Builder setInitialBufferingMode(int);
+    method public android.media.BufferingParams.Builder setInitialBufferingWatermarkKB(int);
+    method public android.media.BufferingParams.Builder setInitialBufferingWatermarkMs(int);
+    method public android.media.BufferingParams.Builder setRebufferingMode(int);
+    method public android.media.BufferingParams.Builder setRebufferingWatermarkHighKB(int);
+    method public android.media.BufferingParams.Builder setRebufferingWatermarkHighMs(int);
+    method public android.media.BufferingParams.Builder setRebufferingWatermarkLowKB(int);
+    method public android.media.BufferingParams.Builder setRebufferingWatermarkLowMs(int);
+    method public android.media.BufferingParams.Builder setRebufferingWatermarksKB(int, int);
+    method public android.media.BufferingParams.Builder setRebufferingWatermarksMs(int, int);
+  }
+
   public class CamcorderProfile {
     method public static android.media.CamcorderProfile get(int);
     method public static android.media.CamcorderProfile get(int, int);
@@ -22852,6 +22928,7 @@
     method public deprecated java.nio.ByteBuffer[] getInputBuffers();
     method public final android.media.MediaFormat getInputFormat();
     method public android.media.Image getInputImage(int);
+    method public android.os.Bundle getMetrics();
     method public final java.lang.String getName();
     method public java.nio.ByteBuffer getOutputBuffer(int);
     method public deprecated java.nio.ByteBuffer[] getOutputBuffers();
@@ -23644,6 +23721,7 @@
 
   public final class MediaMuxer {
     ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException;
+    ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException;
     method public int addTrack(android.media.MediaFormat);
     method public void release();
     method public void setLocation(float, float);
@@ -23672,8 +23750,14 @@
     method public static android.media.MediaPlayer create(android.content.Context, int, android.media.AudioAttributes, int);
     method public void deselectTrack(int) throws java.lang.IllegalStateException;
     method public int getAudioSessionId();
+    method public android.media.BufferingParams getBufferingParams();
     method public int getCurrentPosition();
+    method public android.media.BufferingParams getDefaultBufferingParams();
+    method public android.media.MediaPlayer.DrmInfo getDrmInfo();
+    method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
     method public int getDuration();
+    method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
+    method public android.os.Bundle getMetrics();
     method public android.media.PlaybackParams getPlaybackParams();
     method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
     method public android.media.SyncParams getSyncParams();
@@ -23686,8 +23770,12 @@
     method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
     method public void prepareAsync() throws java.lang.IllegalStateException;
+    method public void prepareDrm(java.util.UUID, android.media.MediaPlayer.OnDrmConfigCallback) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
+    method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.MediaPlayer.NoDrmSchemeException;
     method public void release();
+    method public void releaseDrm() throws android.media.MediaPlayer.NoDrmSchemeException;
     method public void reset();
+    method public void restoreKeys(byte[]) throws android.media.MediaPlayer.NoDrmSchemeException;
     method public void seekTo(int, int) throws java.lang.IllegalStateException;
     method public void seekTo(int) throws java.lang.IllegalStateException;
     method public void selectTrack(int) throws java.lang.IllegalStateException;
@@ -23695,6 +23783,7 @@
     method public void setAudioSessionId(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public deprecated void setAudioStreamType(int);
     method public void setAuxEffectSendLevel(float);
+    method public void setBufferingParams(android.media.BufferingParams);
     method public void setDataSource(android.content.Context, android.net.Uri) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
     method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
     method public void setDataSource(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
@@ -23703,10 +23792,15 @@
     method public void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public void setDataSource(android.media.MediaDataSource) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public void setDisplay(android.view.SurfaceHolder);
+    method public void setDrmPropertyString(java.lang.String, java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
     method public void setLooping(boolean);
     method public void setNextMediaPlayer(android.media.MediaPlayer);
     method public void setOnBufferingUpdateListener(android.media.MediaPlayer.OnBufferingUpdateListener);
     method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
+    method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener);
+    method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener, android.os.Handler);
+    method public void setOnDrmPreparedListener(android.media.MediaPlayer.OnDrmPreparedListener);
+    method public void setOnDrmPreparedListener(android.media.MediaPlayer.OnDrmPreparedListener, android.os.Handler);
     method public void setOnErrorListener(android.media.MediaPlayer.OnErrorListener);
     method public void setOnInfoListener(android.media.MediaPlayer.OnInfoListener);
     method public void setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener);
@@ -23749,6 +23843,16 @@
     field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = 2; // 0x2
   }
 
+  public static final class MediaPlayer.DrmInfo {
+    method public java.lang.String[] getMimes();
+    method public java.util.Map<java.util.UUID, byte[]> getPssh();
+    method public java.util.UUID[] getSupportedSchemes();
+  }
+
+  public static final class MediaPlayer.NoDrmSchemeException extends android.media.MediaDrmException {
+    ctor public MediaPlayer.NoDrmSchemeException(java.lang.String);
+  }
+
   public static abstract interface MediaPlayer.OnBufferingUpdateListener {
     method public abstract void onBufferingUpdate(android.media.MediaPlayer, int);
   }
@@ -23757,6 +23861,19 @@
     method public abstract void onCompletion(android.media.MediaPlayer);
   }
 
+  public static abstract class MediaPlayer.OnDrmConfigCallback {
+    ctor public MediaPlayer.OnDrmConfigCallback();
+    method public void onDrmConfig(android.media.MediaPlayer);
+  }
+
+  public static abstract interface MediaPlayer.OnDrmInfoListener {
+    method public abstract void onDrmInfo(android.media.MediaPlayer, android.media.MediaPlayer.DrmInfo);
+  }
+
+  public static abstract interface MediaPlayer.OnDrmPreparedListener {
+    method public abstract void onDrmPrepared(android.media.MediaPlayer, boolean);
+  }
+
   public static abstract interface MediaPlayer.OnErrorListener {
     method public abstract boolean onError(android.media.MediaPlayer, int, int);
   }
@@ -23785,6 +23902,10 @@
     method public abstract void onVideoSizeChanged(android.media.MediaPlayer, int, int);
   }
 
+  public static final class MediaPlayer.ProvisioningErrorException extends android.media.MediaDrmException {
+    ctor public MediaPlayer.ProvisioningErrorException(java.lang.String);
+  }
+
   public static class MediaPlayer.TrackInfo implements android.os.Parcelable {
     method public int describeContents();
     method public android.media.MediaFormat getFormat();
@@ -25527,7 +25648,16 @@
   }
 
   public static final class TvContract.Programs implements android.media.tv.TvContract.BaseTvColumns {
+    field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
+    field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
+    field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
+    field public static final java.lang.String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
+    field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
+    field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
+    field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
     field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
+    field public static final java.lang.String COLUMN_AUTHOR = "author";
+    field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
     field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
     field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
     field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
@@ -25536,13 +25666,20 @@
     field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
     field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
     field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+    field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
+    field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
     field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
     field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
     field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
     field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
     field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
     field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
+    field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
+    field public static final java.lang.String COLUMN_LIVE = "live";
+    field public static final java.lang.String COLUMN_LOGO = "logo";
     field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+    field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
+    field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
     field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
     field public static final java.lang.String COLUMN_PREVIEW_DURATION = "preview_duration";
     field public static final java.lang.String COLUMN_PREVIEW_INTENT_URI = "preview_intent_uri";
@@ -25550,21 +25687,53 @@
     field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
     field public static final java.lang.String COLUMN_PREVIEW_WEIGHT = "preview_weight";
     field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
+    field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
+    field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
+    field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
     field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
     field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
     field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number";
     field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
     field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
+    field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
     field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
+    field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
     field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
     field public static final java.lang.String COLUMN_TITLE = "title";
     field public static final java.lang.String COLUMN_TRANSIENT = "transient";
+    field public static final java.lang.String COLUMN_TYPE = "type";
     field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
     field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
     field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
+    field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program";
     field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
+    field public static final java.lang.String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
+    field public static final java.lang.String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
+    field public static final java.lang.String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
+    field public static final java.lang.String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
+    field public static final java.lang.String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
+    field public static final java.lang.String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
+    field public static final java.lang.String REVIEW_RATING_STYLE_PERCENTAGE = "REVIEW_RATING_STYLE_PERCENTAGE";
+    field public static final java.lang.String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
+    field public static final java.lang.String REVIEW_RATING_STYLE_THUMBS_UP_DOWN = "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
+    field public static final java.lang.String TYPE_ALBUM = "TYPE_ALBUM";
+    field public static final java.lang.String TYPE_ARTIST = "TYPE_ARTIST";
+    field public static final java.lang.String TYPE_CHANNEL = "TYPE_CHANNEL";
+    field public static final java.lang.String TYPE_CLIP = "TYPE_CLIP";
+    field public static final java.lang.String TYPE_EVENT = "TYPE_EVENT";
+    field public static final java.lang.String TYPE_MOVIE = "TYPE_MOVIE";
+    field public static final java.lang.String TYPE_PLAYLIST = "TYPE_PLAYLIST";
+    field public static final java.lang.String TYPE_STATION = "TYPE_STATION";
+    field public static final java.lang.String TYPE_TRACK = "TYPE_TRACK";
+    field public static final java.lang.String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
+    field public static final java.lang.String TYPE_TV_SEASON = "TYPE_TV_SEASON";
+    field public static final java.lang.String TYPE_TV_SERIES = "TYPE_TV_SERIES";
+    field public static final java.lang.String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
+    field public static final java.lang.String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
+    field public static final java.lang.String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
   }
 
   public static final class TvContract.Programs.Genres {
@@ -25755,10 +25924,13 @@
     method public void unregisterCallback(android.media.tv.TvInputManager.TvInputCallback);
     method public void updateTvInputInfo(android.media.tv.TvInputInfo);
     field public static final java.lang.String ACTION_BLOCKED_RATINGS_CHANGED = "android.media.tv.action.BLOCKED_RATINGS_CHANGED";
+    field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
     field public static final java.lang.String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED = "android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED";
     field public static final java.lang.String ACTION_QUERY_CONTENT_RATING_SYSTEMS = "android.media.tv.action.QUERY_CONTENT_RATING_SYSTEMS";
     field public static final java.lang.String ACTION_SETUP_INPUTS = "android.media.tv.action.SETUP_INPUTS";
     field public static final java.lang.String ACTION_VIEW_RECORDING_SCHEDULES = "android.media.tv.action.VIEW_RECORDING_SCHEDULES";
+    field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
+    field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
     field public static final int INPUT_STATE_CONNECTED = 0; // 0x0
     field public static final int INPUT_STATE_CONNECTED_STANDBY = 1; // 0x1
     field public static final int INPUT_STATE_DISCONNECTED = 2; // 0x2
@@ -26020,6 +26192,7 @@
     ctor public LogMaker(int);
     ctor public LogMaker(java.lang.Object[]);
     method public android.metrics.LogMaker addTaggedData(int, java.lang.Object);
+    method public android.metrics.LogMaker clearTaggedData(int);
     method public void deserialize(java.lang.Object[]);
     method public int getCategory();
     method public long getCounterBucket();
@@ -26031,6 +26204,7 @@
     method public long getTimestamp();
     method public int getType();
     method public boolean isLongCounterBucket();
+    method public boolean isSubsetOf(android.metrics.LogMaker);
     method public boolean isValidValue(java.lang.Object);
     method public java.lang.Object[] serialize();
     method public android.metrics.LogMaker setCategory(int);
@@ -26571,6 +26745,10 @@
     field public static final android.os.Parcelable.Creator<android.net.Network> CREATOR;
   }
 
+  public class NetworkBadging {
+    method public static android.graphics.drawable.Drawable getWifiIcon(int, int, android.content.res.Resources.Theme);
+  }
+
   public final class NetworkCapabilities implements android.os.Parcelable {
     ctor public NetworkCapabilities(android.net.NetworkCapabilities);
     method public int describeContents();
@@ -27964,6 +28142,7 @@
     method public java.security.cert.X509Certificate getCaCertificate();
     method public java.security.cert.X509Certificate[] getCaCertificates();
     method public java.security.cert.X509Certificate getClientCertificate();
+    method public java.security.cert.X509Certificate[] getClientCertificateChain();
     method public java.lang.String getDomainSuffixMatch();
     method public int getEapMethod();
     method public java.lang.String getIdentity();
@@ -27977,6 +28156,7 @@
     method public void setCaCertificate(java.security.cert.X509Certificate);
     method public void setCaCertificates(java.security.cert.X509Certificate[]);
     method public void setClientKeyEntry(java.security.PrivateKey, java.security.cert.X509Certificate);
+    method public void setClientKeyEntryWithCertificateChain(java.security.PrivateKey, java.security.cert.X509Certificate[]);
     method public void setDomainSuffixMatch(java.lang.String);
     method public void setEapMethod(int);
     method public void setIdentity(java.lang.String);
@@ -28063,6 +28243,7 @@
     method public boolean isWifiEnabled();
     method public boolean isWifiScannerSupported();
     method public boolean pingSupplicant();
+    method public void queryPasspointIcon(long, java.lang.String);
     method public boolean reassociate();
     method public boolean reconnect();
     method public boolean removeNetwork(int);
@@ -28077,6 +28258,10 @@
     method public boolean startScan(android.os.WorkSource);
     method public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsCallback);
     method public int updateNetwork(android.net.wifi.WifiConfiguration);
+    field public static final java.lang.String ACTION_PASSPOINT_DEAUTH_IMMINENT = "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT";
+    field public static final java.lang.String ACTION_PASSPOINT_ICON = "android.net.wifi.action.PASSPOINT_ICON";
+    field public static final java.lang.String ACTION_PASSPOINT_OSU_PROVIDERS_LIST = "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST";
+    field public static final java.lang.String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION = "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION";
     field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
     field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
     field public static final int CHANGE_REASON_ADDED = 0; // 0x0
@@ -28090,6 +28275,18 @@
     field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
     field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi";
     field public static final java.lang.String EXTRA_NEW_STATE = "newState";
+    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_BSSID = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_BSSID";
+    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_ESS = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_ESS";
+    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REASON_URL = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REASON_URL";
+    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY";
+    field public static final java.lang.String EXTRA_PASSPOINT_ICON_BSSID = "android.net.wifi.extra.PASSPOINT_ICON_BSSID";
+    field public static final java.lang.String EXTRA_PASSPOINT_ICON_DATA = "android.net.wifi.extra.PASSPOINT_ICON_DATA";
+    field public static final java.lang.String EXTRA_PASSPOINT_ICON_FILENAME = "android.net.wifi.extra.PASSPOINT_ICON_FILENAME";
+    field public static final java.lang.String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_BSSID = "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_BSSID";
+    field public static final java.lang.String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_DATA = "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_DATA";
+    field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID";
+    field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD";
+    field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL";
     field public static final java.lang.String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state";
     field public static final java.lang.String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
     field public static final java.lang.String EXTRA_RESULTS_UPDATED = "resultsUpdated";
@@ -36500,6 +36697,7 @@
     field public static final java.lang.String ACTION_APPLICATION_DETAILS_SETTINGS = "android.settings.APPLICATION_DETAILS_SETTINGS";
     field public static final java.lang.String ACTION_APPLICATION_DEVELOPMENT_SETTINGS = "android.settings.APPLICATION_DEVELOPMENT_SETTINGS";
     field public static final java.lang.String ACTION_APPLICATION_SETTINGS = "android.settings.APPLICATION_SETTINGS";
+    field public static final java.lang.String ACTION_APP_NOTIFICATION_SETTINGS = "android.settings.APP_NOTIFICATION_SETTINGS";
     field public static final java.lang.String ACTION_BATTERY_SAVER_SETTINGS = "android.settings.BATTERY_SAVER_SETTINGS";
     field public static final java.lang.String ACTION_BLUETOOTH_SETTINGS = "android.settings.BLUETOOTH_SETTINGS";
     field public static final java.lang.String ACTION_CAPTIONING_SETTINGS = "android.settings.CAPTIONING_SETTINGS";
@@ -36524,6 +36722,7 @@
     field public static final java.lang.String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
     field public static final java.lang.String ACTION_MANAGE_APPLICATIONS_SETTINGS = "android.settings.MANAGE_APPLICATIONS_SETTINGS";
     field public static final java.lang.String ACTION_MANAGE_DEFAULT_APPS_SETTINGS = "android.settings.MANAGE_DEFAULT_APPS_SETTINGS";
+    field public static final java.lang.String ACTION_MANAGE_EXTERNAL_SOURCES = "android.settings.action.MANAGE_EXTERNAL_SOURCES";
     field public static final java.lang.String ACTION_MANAGE_OVERLAY_PERMISSION = "android.settings.action.MANAGE_OVERLAY_PERMISSION";
     field public static final java.lang.String ACTION_MANAGE_WRITE_SETTINGS = "android.settings.action.MANAGE_WRITE_SETTINGS";
     field public static final java.lang.String ACTION_MEMORY_CARD_SETTINGS = "android.settings.MEMORY_CARD_SETTINGS";
@@ -36682,7 +36881,7 @@
     field public static final java.lang.String ENABLED_INPUT_METHODS = "enabled_input_methods";
     field public static final deprecated java.lang.String HTTP_PROXY = "http_proxy";
     field public static final java.lang.String INPUT_METHOD_SELECTOR_VISIBILITY = "input_method_selector_visibility";
-    field public static final java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
+    field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
     field public static final java.lang.String LOCATION_MODE = "location_mode";
     field public static final int LOCATION_MODE_BATTERY_SAVING = 2; // 0x2
     field public static final int LOCATION_MODE_HIGH_ACCURACY = 3; // 0x3
@@ -37237,6 +37436,8 @@
 
   public static final class VoicemailContract.Voicemails implements android.provider.BaseColumns android.provider.OpenableColumns {
     method public static android.net.Uri buildSourceUri(java.lang.String);
+    field public static final java.lang.String ARCHIVED = "archived";
+    field public static final java.lang.String BACKED_UP = "backed_up";
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String DATE = "date";
     field public static final java.lang.String DELETED = "deleted";
@@ -37244,6 +37445,7 @@
     field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemails";
     field public static final java.lang.String DURATION = "duration";
     field public static final java.lang.String HAS_CONTENT = "has_content";
+    field public static final java.lang.String IS_OMTP_VOICEMAIL = "is_omtp_voicemail";
     field public static final java.lang.String IS_READ = "is_read";
     field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail";
     field public static final java.lang.String LAST_MODIFIED = "last_modified";
@@ -37251,6 +37453,7 @@
     field public static final java.lang.String NUMBER = "number";
     field public static final java.lang.String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name";
     field public static final java.lang.String PHONE_ACCOUNT_ID = "subscription_id";
+    field public static final java.lang.String RESTORED = "restored";
     field public static final java.lang.String SOURCE_DATA = "source_data";
     field public static final java.lang.String SOURCE_PACKAGE = "source_package";
     field public static final java.lang.String TRANSCRIPTION = "transcription";
@@ -38640,17 +38843,25 @@
     ctor public AutoFillService();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConnected();
+    method public void onDatasetAuthenticationRequest(android.os.Bundle, int);
     method public void onDisconnected();
     method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback);
-    method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.SaveCallback);
+    method public void onFillResponseAuthenticationRequest(android.os.Bundle, int);
+    method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
     field public static final java.lang.String EXTRA_DATASET_EXTRAS = "android.service.autofill.extra.DATASET_EXTRAS";
     field public static final java.lang.String EXTRA_RESPONSE_EXTRAS = "android.service.autofill.extra.RESPONSE_EXTRAS";
+    field public static final int FLAG_AUTHENTICATION_ERROR = 4; // 0x4
+    field public static final int FLAG_AUTHENTICATION_REQUESTED = 1; // 0x1
+    field public static final int FLAG_AUTHENTICATION_SUCCESS = 2; // 0x2
+    field public static final int FLAG_FINGERPRINT_AUTHENTICATION_NOT_AVAILABLE = 8; // 0x8
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
     field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
   }
 
   public final class FillCallback {
+    method public void onDatasetAuthentication(android.view.autofill.Dataset, int);
     method public void onFailure(java.lang.CharSequence);
+    method public void onFillResponseAuthentication(int);
     method public void onSuccess(android.view.autofill.FillResponse);
   }
 
@@ -41354,6 +41565,7 @@
     field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING = "ci_action_on_sys_update_extra_string";
     field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING = "ci_action_on_sys_update_extra_val_string";
     field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING = "ci_action_on_sys_update_intent_string";
+    field public static final java.lang.String KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING = "config_ims_package_override_string";
     field public static final java.lang.String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool";
     field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
     field public static final java.lang.String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string";
@@ -42011,6 +42223,7 @@
     method public int getSimState(int);
     method public java.lang.String getSubscriberId();
     method public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
+    method public java.lang.String getVisualVoicemailPackageName(android.telecom.PhoneAccountHandle);
     method public java.lang.String getVoiceMailAlphaTag();
     method public java.lang.String getVoiceMailNumber();
     method public int getVoiceNetworkType();
@@ -42041,6 +42254,7 @@
     method public boolean isWorldPhone();
     method public void listen(android.telephony.PhoneStateListener, int);
     method public boolean needsOtaServiceProvisioning();
+    method public boolean sendDialerCode(java.lang.String);
     method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
     method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
     method public void sendUssdRequest(java.lang.String, int, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
@@ -42089,6 +42303,7 @@
     field public static final int DATA_DISCONNECTED = 0; // 0x0
     field public static final int DATA_SUSPENDED = 3; // 0x3
     field public static final java.lang.String EXTRA_CALL_VOICEMAIL_INTENT = "android.telephony.extra.CALL_VOICEMAIL_INTENT";
+    field public static final java.lang.String EXTRA_HIDE_PUBLIC_SETTINGS = "android.telephony.extra.HIDE_PUBLIC_SETTINGS";
     field public static final java.lang.String EXTRA_INCOMING_NUMBER = "incoming_number";
     field public static final java.lang.String EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT = "android.telephony.extra.LAUNCH_VOICEMAIL_SETTINGS_INTENT";
     field public static final java.lang.String EXTRA_NOTIFICATION_COUNT = "android.telephony.extra.NOTIFICATION_COUNT";
@@ -42097,6 +42312,7 @@
     field public static final java.lang.String EXTRA_STATE_OFFHOOK;
     field public static final java.lang.String EXTRA_STATE_RINGING;
     field public static final java.lang.String EXTRA_VOICEMAIL_NUMBER = "android.telephony.extra.VOICEMAIL_NUMBER";
+    field public static final java.lang.String METADATA_HIDE_VOICEMAIL_SETTINGS_MENU = "android.telephony.HIDE_VOICEMAIL_SETTINGS_MENU";
     field public static final int NETWORK_TYPE_1xRTT = 7; // 0x7
     field public static final int NETWORK_TYPE_CDMA = 4; // 0x4
     field public static final int NETWORK_TYPE_EDGE = 2; // 0x2
@@ -42303,6 +42519,15 @@
 
 }
 
+package android.telephony.ims {
+
+  public class ImsServiceBase extends android.app.Service {
+    ctor public ImsServiceBase();
+    method public android.os.IBinder onBind(android.content.Intent);
+  }
+
+}
+
 package android.test {
 
   public abstract deprecated class ActivityInstrumentationTestCase<T extends android.app.Activity> extends android.test.ActivityTestCase {
@@ -42801,6 +43026,7 @@
     method public boolean addPermission(android.content.pm.PermissionInfo);
     method public boolean addPermissionAsync(android.content.pm.PermissionInfo);
     method public void addPreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName);
+    method public boolean canRequestPackageInstalls();
     method public java.lang.String[] canonicalToCurrentPackageNames(java.lang.String[]);
     method public int checkPermission(java.lang.String, java.lang.String);
     method public int checkSignatures(java.lang.String, java.lang.String);
@@ -45799,6 +46025,7 @@
     field public static final int FLAG_PRIVATE = 4; // 0x4
     field public static final int FLAG_ROUND = 16; // 0x10
     field public static final int FLAG_SECURE = 2; // 0x2
+    field public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
     field public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1; // 0x1
     field public static final int INVALID_DISPLAY = -1; // 0xffffffff
     field public static final int STATE_DOZE = 3; // 0x3
@@ -46045,6 +46272,7 @@
     field public static final int SOURCE_JOYSTICK = 16777232; // 0x1000010
     field public static final int SOURCE_KEYBOARD = 257; // 0x101
     field public static final int SOURCE_MOUSE = 8194; // 0x2002
+    field public static final int SOURCE_MOUSE_RELATIVE = 131076; // 0x20004
     field public static final int SOURCE_STYLUS = 16386; // 0x4002
     field public static final int SOURCE_TOUCHPAD = 1048584; // 0x100008
     field public static final int SOURCE_TOUCHSCREEN = 4098; // 0x1002
@@ -47199,6 +47427,7 @@
     method public void createContextMenu(android.view.ContextMenu);
     method public void destroyDrawingCache();
     method public android.view.WindowInsets dispatchApplyWindowInsets(android.view.WindowInsets);
+    method public boolean dispatchCapturedPointerEvent(android.view.MotionEvent);
     method public void dispatchConfigurationChanged(android.content.res.Configuration);
     method public void dispatchDisplayHint(int);
     method public boolean dispatchDragEvent(android.view.DragEvent);
@@ -47217,6 +47446,7 @@
     method public boolean dispatchNestedPrePerformAccessibilityAction(int, android.os.Bundle);
     method public boolean dispatchNestedPreScroll(int, int, int[], int[]);
     method public boolean dispatchNestedScroll(int, int, int, int, int[]);
+    method public void dispatchPointerCaptureChanged(boolean);
     method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public void dispatchProvideAutoFillStructure(android.view.ViewStructure, int);
     method public void dispatchProvideStructure(android.view.ViewStructure);
@@ -47368,7 +47598,6 @@
     method public java.lang.Object getTag(int);
     method public int getTextAlignment();
     method public int getTextDirection();
-    method public final deprecated java.lang.CharSequence getTooltip();
     method public final java.lang.CharSequence getTooltipText();
     method public final int getTop();
     method protected float getTopFadingEdgeStrength();
@@ -47399,6 +47628,7 @@
     method public boolean hasNestedScrollingParent();
     method public boolean hasOnClickListeners();
     method public boolean hasOverlappingRendering();
+    method public boolean hasPointerCapture();
     method public boolean hasTransientState();
     method public boolean hasWindowFocus();
     method public static android.view.View inflate(android.content.Context, int, android.view.ViewGroup);
@@ -47463,6 +47693,7 @@
     method public android.view.WindowInsets onApplyWindowInsets(android.view.WindowInsets);
     method protected void onAttachedToWindow();
     method public void onCancelPendingInputEvents();
+    method public boolean onCapturedPointerEvent(android.view.MotionEvent);
     method public boolean onCheckIsTextEditor();
     method protected void onConfigurationChanged(android.content.res.Configuration);
     method protected void onCreateContextMenu(android.view.ContextMenu);
@@ -47492,6 +47723,7 @@
     method protected void onLayout(boolean, int, int, int, int);
     method protected void onMeasure(int, int);
     method protected void onOverScrolled(int, int, boolean, boolean);
+    method public void onPointerCaptureChange(boolean);
     method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public void onProvideAutoFillStructure(android.view.ViewStructure, int);
     method public void onProvideAutoFillVirtualStructure(android.view.ViewStructure, int);
@@ -47534,6 +47766,7 @@
     method public void postOnAnimation(java.lang.Runnable);
     method public void postOnAnimationDelayed(java.lang.Runnable, long);
     method public void refreshDrawableState();
+    method public void releasePointerCapture();
     method public boolean removeCallbacks(java.lang.Runnable);
     method public void removeOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
     method public void removeOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
@@ -47544,6 +47777,7 @@
     method public boolean requestFocus(int, android.graphics.Rect);
     method public final boolean requestFocusFromTouch();
     method public void requestLayout();
+    method public void requestPointerCapture();
     method public boolean requestRectangleOnScreen(android.graphics.Rect);
     method public boolean requestRectangleOnScreen(android.graphics.Rect, boolean);
     method public final void requestUnbufferedDispatch(android.view.MotionEvent);
@@ -47621,6 +47855,7 @@
     method public void setNextFocusRightId(int);
     method public void setNextFocusUpId(int);
     method public void setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener);
+    method public void setOnCapturedPointerListener(android.view.View.OnCapturedPointerListener);
     method public void setOnClickListener(android.view.View.OnClickListener);
     method public void setOnContextClickListener(android.view.View.OnContextClickListener);
     method public void setOnCreateContextMenuListener(android.view.View.OnCreateContextMenuListener);
@@ -47668,7 +47903,6 @@
     method public void setTag(int, java.lang.Object);
     method public void setTextAlignment(int);
     method public void setTextDirection(int);
-    method public final deprecated void setTooltip(java.lang.CharSequence);
     method public final void setTooltipText(java.lang.CharSequence);
     method public final void setTop(int);
     method public void setTouchDelegate(android.view.TouchDelegate);
@@ -47704,8 +47938,8 @@
     field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
     field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
     field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
-    field public static final int AUTO_FILL_FLAG_TYPE_FILL = 1; // 0x1
-    field public static final int AUTO_FILL_FLAG_TYPE_SAVE = 2; // 0x2
+    field public static final int AUTO_FILL_FLAG_TYPE_FILL = 268435456; // 0x10000000
+    field public static final int AUTO_FILL_FLAG_TYPE_SAVE = 536870912; // 0x20000000
     field public static final int DRAG_FLAG_GLOBAL = 256; // 0x100
     field public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION = 64; // 0x40
     field public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION = 128; // 0x80
@@ -47894,6 +48128,10 @@
     method public abstract void onViewDetachedFromWindow(android.view.View);
   }
 
+  public static abstract interface View.OnCapturedPointerListener {
+    method public abstract boolean onCapturedPointer(android.view.View, android.view.MotionEvent);
+  }
+
   public static abstract interface View.OnClickListener {
     method public abstract void onClick(android.view.View);
   }
@@ -48627,6 +48865,7 @@
     method public abstract boolean onMenuItemSelected(int, android.view.MenuItem);
     method public abstract boolean onMenuOpened(int, android.view.Menu);
     method public abstract void onPanelClosed(int, android.view.Menu);
+    method public default void onPointerCaptureChanged(boolean);
     method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
     method public default void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu, int);
     method public abstract boolean onSearchRequested();
@@ -49636,6 +49875,8 @@
   public static final class Dataset.Builder {
     ctor public Dataset.Builder(java.lang.CharSequence);
     method public android.view.autofill.Dataset build();
+    method public android.view.autofill.Dataset.Builder requiresCustomAuthentication(android.os.Bundle, int);
+    method public android.view.autofill.Dataset.Builder requiresFingerprintAuthentication(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.Bundle, int);
     method public android.view.autofill.Dataset.Builder setExtras(android.os.Bundle);
     method public android.view.autofill.Dataset.Builder setValue(android.view.autofill.AutoFillId, android.view.autofill.AutoFillValue);
   }
@@ -49651,6 +49892,8 @@
     method public android.view.autofill.FillResponse.Builder addDataset(android.view.autofill.Dataset);
     method public android.view.autofill.FillResponse.Builder addSavableFields(android.view.autofill.AutoFillId...);
     method public android.view.autofill.FillResponse build();
+    method public android.view.autofill.FillResponse.Builder requiresCustomAuthentication(android.os.Bundle, int);
+    method public android.view.autofill.FillResponse.Builder requiresFingerprintAuthentication(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.Bundle, int);
     method public android.view.autofill.FillResponse.Builder setExtras(android.os.Bundle);
   }
 
@@ -52800,6 +53043,7 @@
     method public android.graphics.PorterDuff.Mode getSecondaryProgressTintMode();
     method public final synchronized void incrementProgressBy(int);
     method public final synchronized void incrementSecondaryProgressBy(int);
+    method public boolean isAnimating();
     method public synchronized boolean isIndeterminate();
     method public void onRestoreInstanceState(android.os.Parcelable);
     method public android.os.Parcelable onSaveInstanceState();
diff --git a/api/test-current.txt b/api/test-current.txt
index 15844cd..a32300e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1119,6 +1119,7 @@
     field public static final int searchSuggestSelection = 16843224; // 0x10101d8
     field public static final int searchSuggestThreshold = 16843373; // 0x101026d
     field public static final int searchViewStyle = 16843904; // 0x1010480
+    field public static final int secondaryContentAlpha = 16843688; // 0x10103a8
     field public static final int secondaryProgress = 16843064; // 0x1010138
     field public static final int secondaryProgressTint = 16843879; // 0x1010467
     field public static final int secondaryProgressTintMode = 16843880; // 0x1010468
@@ -3554,6 +3555,7 @@
     method public android.view.WindowManager getWindowManager();
     method public boolean hasWindowFocus();
     method public void invalidateOptionsMenu();
+    method public boolean isActivityTransitionRunning();
     method public boolean isChangingConfigurations();
     method public final boolean isChild();
     method public boolean isDestroyed();
@@ -5060,6 +5062,7 @@
     field public static final java.lang.String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
     field public static final java.lang.String EXTRA_BIG_TEXT = "android.bigText";
     field public static final java.lang.String EXTRA_CHRONOMETER_COUNT_DOWN = "android.chronometerCountDown";
+    field public static final java.lang.String EXTRA_COLORIZED = "android.colorized";
     field public static final java.lang.String EXTRA_COMPACT_ACTIONS = "android.compactActions";
     field public static final java.lang.String EXTRA_CONVERSATION_TITLE = "android.conversationTitle";
     field public static final java.lang.String EXTRA_HISTORIC_MESSAGES = "android.messages.historic";
@@ -5206,7 +5209,8 @@
   }
 
   public static class Notification.Builder {
-    ctor public Notification.Builder(android.content.Context);
+    ctor public Notification.Builder(android.content.Context, java.lang.String);
+    ctor public deprecated Notification.Builder(android.content.Context);
     method public deprecated android.app.Notification.Builder addAction(int, java.lang.CharSequence, android.app.PendingIntent);
     method public android.app.Notification.Builder addAction(android.app.Notification.Action);
     method public android.app.Notification.Builder addExtras(android.os.Bundle);
@@ -5225,6 +5229,7 @@
     method public android.app.Notification.Builder setChannel(java.lang.String);
     method public android.app.Notification.Builder setChronometerCountDown(boolean);
     method public android.app.Notification.Builder setColor(int);
+    method public android.app.Notification.Builder setColorized(boolean);
     method public deprecated android.app.Notification.Builder setContent(android.widget.RemoteViews);
     method public deprecated android.app.Notification.Builder setContentInfo(java.lang.CharSequence);
     method public android.app.Notification.Builder setContentIntent(android.app.PendingIntent);
@@ -5428,6 +5433,8 @@
     method public boolean canShowBadge();
     method public int describeContents();
     method public void enableVibration(boolean);
+    method public android.media.AudioAttributes getAudioAttributes();
+    method public java.lang.String getGroup();
     method public java.lang.String getId();
     method public int getImportance();
     method public int getLockscreenVisibility();
@@ -5435,11 +5442,12 @@
     method public android.net.Uri getSound();
     method public long[] getVibrationPattern();
     method public void setBypassDnd(boolean);
+    method public void setGroup(java.lang.String);
     method public void setImportance(int);
     method public void setLights(boolean);
     method public void setLockscreenVisibility(int);
     method public void setShowBadge(boolean);
-    method public void setSound(android.net.Uri);
+    method public void setSound(android.net.Uri, android.media.AudioAttributes);
     method public void setVibrationPattern(long[]);
     method public boolean shouldShowLights();
     method public boolean shouldVibrate();
@@ -5448,6 +5456,17 @@
     field public static final java.lang.String DEFAULT_CHANNEL_ID = "miscellaneous";
   }
 
+  public final class NotificationChannelGroup implements android.os.Parcelable {
+    ctor public NotificationChannelGroup(java.lang.String, java.lang.CharSequence);
+    ctor protected NotificationChannelGroup(android.os.Parcel);
+    method public int describeContents();
+    method public java.util.List<android.app.NotificationChannel> getChannels();
+    method public java.lang.String getId();
+    method public java.lang.CharSequence getName();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.app.NotificationChannelGroup> CREATOR;
+  }
+
   public class NotificationManager {
     method public java.lang.String addAutomaticZenRule(android.app.AutomaticZenRule);
     method public boolean areNotificationsEnabled();
@@ -5455,6 +5474,8 @@
     method public void cancel(java.lang.String, int);
     method public void cancelAll();
     method public void createNotificationChannel(android.app.NotificationChannel);
+    method public void createNotificationChannelGroup(android.app.NotificationChannelGroup);
+    method public void createNotificationChannelGroups(java.util.List<android.app.NotificationChannelGroup>);
     method public void createNotificationChannels(java.util.List<android.app.NotificationChannel>);
     method public void deleteNotificationChannel(java.lang.String);
     method public android.service.notification.StatusBarNotification[] getActiveNotifications();
@@ -6140,6 +6161,7 @@
     method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
     method public void clearProfileOwner(android.content.ComponentName);
     method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
+    method public android.content.Intent createAdminSupportIntent(java.lang.String);
     method public android.os.UserHandle createAndManageUser(android.content.ComponentName, java.lang.String, android.content.ComponentName, android.os.PersistableBundle, int);
     method public void enableSystemApp(android.content.ComponentName, java.lang.String);
     method public int enableSystemApp(android.content.ComponentName, android.content.Intent);
@@ -6348,6 +6370,7 @@
     field public static final java.lang.String EXTRA_PROVISIONING_WIFI_PROXY_PORT = "android.app.extra.PROVISIONING_WIFI_PROXY_PORT";
     field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SECURITY_TYPE = "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE";
     field public static final java.lang.String EXTRA_PROVISIONING_WIFI_SSID = "android.app.extra.PROVISIONING_WIFI_SSID";
+    field public static final java.lang.String EXTRA_RESTRICTION = "android.app.extra.RESTRICTION";
     field public static final int FLAG_EVICT_CE_KEY = 1; // 0x1
     field public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 2; // 0x2
     field public static final int FLAG_PARENT_CAN_ACCESS_MANAGED = 1; // 0x1
@@ -6375,6 +6398,8 @@
     field public static final int PERMISSION_POLICY_AUTO_DENY = 2; // 0x2
     field public static final int PERMISSION_POLICY_AUTO_GRANT = 1; // 0x1
     field public static final int PERMISSION_POLICY_PROMPT = 0; // 0x0
+    field public static final java.lang.String POLICY_DISABLE_CAMERA = "policy_disable_camera";
+    field public static final java.lang.String POLICY_DISABLE_SCREEN_CAPTURE = "policy_disable_screen_capture";
     field public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2
     field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1
     field public static final int SKIP_SETUP_WIZARD = 1; // 0x1
@@ -6912,6 +6937,7 @@
     method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
     method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
     method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
+    method public boolean isRequestPinAppWidgetSupported();
     method public void notifyAppWidgetViewDataChanged(int[], int);
     method public void notifyAppWidgetViewDataChanged(int, int);
     method public void partiallyUpdateAppWidget(int[], android.widget.RemoteViews);
@@ -9796,6 +9822,7 @@
     field public int theme;
     field public int uiOptions;
     field public int uid;
+    field public java.lang.String volumeUuid;
   }
 
   public static class ApplicationInfo.DisplayNameComparator implements java.util.Comparator {
@@ -9925,7 +9952,8 @@
     method public void startShortcut(java.lang.String, java.lang.String, android.graphics.Rect, android.os.Bundle, android.os.UserHandle);
     method public void startShortcut(android.content.pm.ShortcutInfo, android.graphics.Rect, android.os.Bundle);
     method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
-    field public static final java.lang.String ACTION_CONFIRM_PIN_ITEM = "android.content.pm.action.CONFIRM_PIN_ITEM";
+    field public static final java.lang.String ACTION_CONFIRM_PIN_APPWIDGET = "android.content.pm.action.CONFIRM_PIN_APPWIDGET";
+    field public static final java.lang.String ACTION_CONFIRM_PIN_SHORTCUT = "android.content.pm.action.CONFIRM_PIN_SHORTCUT";
     field public static final java.lang.String EXTRA_PIN_ITEM_REQUEST = "android.content.pm.extra.PIN_ITEM_REQUEST";
   }
 
@@ -10123,6 +10151,7 @@
     method public abstract boolean addPermission(android.content.pm.PermissionInfo);
     method public abstract boolean addPermissionAsync(android.content.pm.PermissionInfo);
     method public abstract deprecated void addPreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName);
+    method public abstract boolean canRequestPackageInstalls();
     method public abstract java.lang.String[] canonicalToCurrentPackageNames(java.lang.String[]);
     method public abstract int checkPermission(java.lang.String, java.lang.String);
     method public abstract int checkSignatures(java.lang.String, java.lang.String);
@@ -10188,6 +10217,7 @@
     method public abstract android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
     method public abstract boolean hasSystemFeature(java.lang.String);
     method public abstract boolean hasSystemFeature(java.lang.String, int);
+    method public abstract boolean isPermissionReviewModeEnabled();
     method public abstract boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
     method public abstract boolean isSafeMode();
     method public abstract java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
@@ -10870,6 +10900,7 @@
     method public int getDimensionPixelSize(int, int);
     method public android.graphics.drawable.Drawable getDrawable(int);
     method public float getFloat(int, float);
+    method public android.graphics.Typeface getFont(int);
     method public float getFraction(int, int, int, float);
     method public int getIndex(int);
     method public int getIndexCount();
@@ -14947,6 +14978,7 @@
     field public static final android.hardware.camera2.CaptureRequest.Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AWB_REGIONS;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_CAPTURE_INTENT;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_EFFECT_MODE;
+    field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Boolean> CONTROL_ENABLE_ZSL;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_MODE;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_POST_RAW_SENSITIVITY_BOOST;
     field public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_SCENE_MODE;
@@ -15026,6 +15058,7 @@
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_AWB_STATE;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_CAPTURE_INTENT;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_EFFECT_MODE;
+    field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Boolean> CONTROL_ENABLE_ZSL;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_MODE;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_POST_RAW_SENSITIVITY_BOOST;
     field public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_SCENE_MODE;
@@ -15251,6 +15284,7 @@
     field public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 2; // 0x2
     field public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1; // 0x1
     field public static final int VIRTUAL_DISPLAY_FLAG_SECURE = 4; // 0x4
+    field public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
   }
 
   public static abstract interface DisplayManager.DisplayListener {
@@ -20472,7 +20506,7 @@
     field public static final android.os.Parcelable.Creator<android.media.AudioAttributes> CREATOR;
     field public static final int FLAG_AUDIBILITY_ENFORCED = 1; // 0x1
     field public static final int FLAG_HW_AV_SYNC = 16; // 0x10
-    field public static final int FLAG_LOW_LATENCY = 256; // 0x100
+    field public static final deprecated int FLAG_LOW_LATENCY = 256; // 0x100
     field public static final int USAGE_ALARM = 4; // 0x4
     field public static final int USAGE_ASSISTANCE_ACCESSIBILITY = 11; // 0xb
     field public static final int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12; // 0xc
@@ -20913,6 +20947,7 @@
     method protected deprecated int getNativeFrameCount();
     method public static int getNativeOutputSampleRate(int);
     method public int getNotificationMarkerPosition();
+    method public int getPerformanceMode();
     method public int getPlayState();
     method public int getPlaybackHeadPosition();
     method public android.media.PlaybackParams getPlaybackParams();
@@ -20959,6 +20994,9 @@
     field public static final int ERROR_INVALID_OPERATION = -3; // 0xfffffffd
     field public static final int MODE_STATIC = 0; // 0x0
     field public static final int MODE_STREAM = 1; // 0x1
+    field public static final int PERFORMANCE_MODE_LOW_LATENCY = 1; // 0x1
+    field public static final int PERFORMANCE_MODE_NONE = 0; // 0x0
+    field public static final int PERFORMANCE_MODE_POWER_SAVING = 2; // 0x2
     field public static final int PLAYSTATE_PAUSED = 2; // 0x2
     field public static final int PLAYSTATE_PLAYING = 3; // 0x3
     field public static final int PLAYSTATE_STOPPED = 1; // 0x1
@@ -20976,6 +21014,7 @@
     method public android.media.AudioTrack.Builder setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException;
     method public android.media.AudioTrack.Builder setAudioFormat(android.media.AudioFormat) throws java.lang.IllegalArgumentException;
     method public android.media.AudioTrack.Builder setBufferSizeInBytes(int) throws java.lang.IllegalArgumentException;
+    method public android.media.AudioTrack.Builder setPerformanceMode(int);
     method public android.media.AudioTrack.Builder setSessionId(int) throws java.lang.IllegalArgumentException;
     method public android.media.AudioTrack.Builder setTransferMode(int) throws java.lang.IllegalArgumentException;
   }
@@ -20990,6 +21029,40 @@
     method public default void onRoutingChanged(android.media.AudioRouting);
   }
 
+  public final class BufferingParams implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getInitialBufferingMode();
+    method public int getInitialBufferingWatermarkKB();
+    method public int getInitialBufferingWatermarkMs();
+    method public int getRebufferingMode();
+    method public int getRebufferingWatermarkHighKB();
+    method public int getRebufferingWatermarkHighMs();
+    method public int getRebufferingWatermarkLowKB();
+    method public int getRebufferingWatermarkLowMs();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int BUFFERING_MODE_NONE = 0; // 0x0
+    field public static final int BUFFERING_MODE_SIZE_ONLY = 2; // 0x2
+    field public static final int BUFFERING_MODE_TIME_ONLY = 1; // 0x1
+    field public static final int BUFFERING_MODE_TIME_THEN_SIZE = 3; // 0x3
+    field public static final android.os.Parcelable.Creator<android.media.BufferingParams> CREATOR;
+  }
+
+  public static class BufferingParams.Builder {
+    ctor public BufferingParams.Builder();
+    ctor public BufferingParams.Builder(android.media.BufferingParams);
+    method public android.media.BufferingParams build();
+    method public android.media.BufferingParams.Builder setInitialBufferingMode(int);
+    method public android.media.BufferingParams.Builder setInitialBufferingWatermarkKB(int);
+    method public android.media.BufferingParams.Builder setInitialBufferingWatermarkMs(int);
+    method public android.media.BufferingParams.Builder setRebufferingMode(int);
+    method public android.media.BufferingParams.Builder setRebufferingWatermarkHighKB(int);
+    method public android.media.BufferingParams.Builder setRebufferingWatermarkHighMs(int);
+    method public android.media.BufferingParams.Builder setRebufferingWatermarkLowKB(int);
+    method public android.media.BufferingParams.Builder setRebufferingWatermarkLowMs(int);
+    method public android.media.BufferingParams.Builder setRebufferingWatermarksKB(int, int);
+    method public android.media.BufferingParams.Builder setRebufferingWatermarksMs(int, int);
+  }
+
   public class CamcorderProfile {
     method public static android.media.CamcorderProfile get(int);
     method public static android.media.CamcorderProfile get(int, int);
@@ -21342,6 +21415,7 @@
     method public deprecated java.nio.ByteBuffer[] getInputBuffers();
     method public final android.media.MediaFormat getInputFormat();
     method public android.media.Image getInputImage(int);
+    method public android.os.Bundle getMetrics();
     method public final java.lang.String getName();
     method public java.nio.ByteBuffer getOutputBuffer(int);
     method public deprecated java.nio.ByteBuffer[] getOutputBuffers();
@@ -22134,6 +22208,7 @@
 
   public final class MediaMuxer {
     ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException;
+    ctor public MediaMuxer(java.io.FileDescriptor, int) throws java.io.IOException;
     method public int addTrack(android.media.MediaFormat);
     method public void release();
     method public void setLocation(float, float);
@@ -22162,8 +22237,14 @@
     method public static android.media.MediaPlayer create(android.content.Context, int, android.media.AudioAttributes, int);
     method public void deselectTrack(int) throws java.lang.IllegalStateException;
     method public int getAudioSessionId();
+    method public android.media.BufferingParams getBufferingParams();
     method public int getCurrentPosition();
+    method public android.media.BufferingParams getDefaultBufferingParams();
+    method public android.media.MediaPlayer.DrmInfo getDrmInfo();
+    method public java.lang.String getDrmPropertyString(java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
     method public int getDuration();
+    method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], java.lang.String, int, java.util.Map<java.lang.String, java.lang.String>) throws android.media.MediaPlayer.NoDrmSchemeException;
+    method public android.os.Bundle getMetrics();
     method public android.media.PlaybackParams getPlaybackParams();
     method public int getSelectedTrack(int) throws java.lang.IllegalStateException;
     method public android.media.SyncParams getSyncParams();
@@ -22176,8 +22257,12 @@
     method public void pause() throws java.lang.IllegalStateException;
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
     method public void prepareAsync() throws java.lang.IllegalStateException;
+    method public void prepareDrm(java.util.UUID, android.media.MediaPlayer.OnDrmConfigCallback) throws android.media.MediaPlayer.ProvisioningErrorException, android.media.ResourceBusyException, android.media.UnsupportedSchemeException;
+    method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.MediaPlayer.NoDrmSchemeException;
     method public void release();
+    method public void releaseDrm() throws android.media.MediaPlayer.NoDrmSchemeException;
     method public void reset();
+    method public void restoreKeys(byte[]) throws android.media.MediaPlayer.NoDrmSchemeException;
     method public void seekTo(int, int) throws java.lang.IllegalStateException;
     method public void seekTo(int) throws java.lang.IllegalStateException;
     method public void selectTrack(int) throws java.lang.IllegalStateException;
@@ -22185,6 +22270,7 @@
     method public void setAudioSessionId(int) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public deprecated void setAudioStreamType(int);
     method public void setAuxEffectSendLevel(float);
+    method public void setBufferingParams(android.media.BufferingParams);
     method public void setDataSource(android.content.Context, android.net.Uri) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
     method public void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
     method public void setDataSource(java.lang.String) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException, java.lang.SecurityException;
@@ -22193,10 +22279,15 @@
     method public void setDataSource(java.io.FileDescriptor, long, long) throws java.io.IOException, java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public void setDataSource(android.media.MediaDataSource) throws java.lang.IllegalArgumentException, java.lang.IllegalStateException;
     method public void setDisplay(android.view.SurfaceHolder);
+    method public void setDrmPropertyString(java.lang.String, java.lang.String) throws android.media.MediaPlayer.NoDrmSchemeException;
     method public void setLooping(boolean);
     method public void setNextMediaPlayer(android.media.MediaPlayer);
     method public void setOnBufferingUpdateListener(android.media.MediaPlayer.OnBufferingUpdateListener);
     method public void setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener);
+    method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener);
+    method public void setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener, android.os.Handler);
+    method public void setOnDrmPreparedListener(android.media.MediaPlayer.OnDrmPreparedListener);
+    method public void setOnDrmPreparedListener(android.media.MediaPlayer.OnDrmPreparedListener, android.os.Handler);
     method public void setOnErrorListener(android.media.MediaPlayer.OnErrorListener);
     method public void setOnInfoListener(android.media.MediaPlayer.OnInfoListener);
     method public void setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener);
@@ -22239,6 +22330,16 @@
     field public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = 2; // 0x2
   }
 
+  public static final class MediaPlayer.DrmInfo {
+    method public java.lang.String[] getMimes();
+    method public java.util.Map<java.util.UUID, byte[]> getPssh();
+    method public java.util.UUID[] getSupportedSchemes();
+  }
+
+  public static final class MediaPlayer.NoDrmSchemeException extends android.media.MediaDrmException {
+    ctor public MediaPlayer.NoDrmSchemeException(java.lang.String);
+  }
+
   public static abstract interface MediaPlayer.OnBufferingUpdateListener {
     method public abstract void onBufferingUpdate(android.media.MediaPlayer, int);
   }
@@ -22247,6 +22348,19 @@
     method public abstract void onCompletion(android.media.MediaPlayer);
   }
 
+  public static abstract class MediaPlayer.OnDrmConfigCallback {
+    ctor public MediaPlayer.OnDrmConfigCallback();
+    method public void onDrmConfig(android.media.MediaPlayer);
+  }
+
+  public static abstract interface MediaPlayer.OnDrmInfoListener {
+    method public abstract void onDrmInfo(android.media.MediaPlayer, android.media.MediaPlayer.DrmInfo);
+  }
+
+  public static abstract interface MediaPlayer.OnDrmPreparedListener {
+    method public abstract void onDrmPrepared(android.media.MediaPlayer, boolean);
+  }
+
   public static abstract interface MediaPlayer.OnErrorListener {
     method public abstract boolean onError(android.media.MediaPlayer, int, int);
   }
@@ -22275,6 +22389,10 @@
     method public abstract void onVideoSizeChanged(android.media.MediaPlayer, int, int);
   }
 
+  public static final class MediaPlayer.ProvisioningErrorException extends android.media.MediaDrmException {
+    ctor public MediaPlayer.ProvisioningErrorException(java.lang.String);
+  }
+
   public static class MediaPlayer.TrackInfo implements android.os.Parcelable {
     method public int describeContents();
     method public android.media.MediaFormat getFormat();
@@ -23874,7 +23992,16 @@
   }
 
   public static final class TvContract.Programs implements android.media.tv.TvContract.BaseTvColumns {
+    field public static final java.lang.String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
+    field public static final java.lang.String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
+    field public static final java.lang.String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
+    field public static final java.lang.String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
+    field public static final java.lang.String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
+    field public static final java.lang.String AVAILABILITY_FREE_WITH_SUBSCRIPTION = "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
+    field public static final java.lang.String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
     field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
+    field public static final java.lang.String COLUMN_AUTHOR = "author";
+    field public static final java.lang.String COLUMN_AVAILABILITY = "availability";
     field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
     field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
     field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
@@ -23883,13 +24010,20 @@
     field public static final java.lang.String COLUMN_EPISODE_DISPLAY_NUMBER = "episode_display_number";
     field public static final deprecated java.lang.String COLUMN_EPISODE_NUMBER = "episode_number";
     field public static final java.lang.String COLUMN_EPISODE_TITLE = "episode_title";
+    field public static final java.lang.String COLUMN_INTERACTION_COUNT = "interaction_count";
+    field public static final java.lang.String COLUMN_INTERACTION_TYPE = "interaction_type";
     field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
     field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG1 = "internal_provider_flag1";
     field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG2 = "internal_provider_flag2";
     field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG3 = "internal_provider_flag3";
     field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_FLAG4 = "internal_provider_flag4";
     field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_ID = "internal_provider_id";
+    field public static final java.lang.String COLUMN_ITEM_COUNT = "item_count";
+    field public static final java.lang.String COLUMN_LIVE = "live";
+    field public static final java.lang.String COLUMN_LOGO = "logo";
     field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+    field public static final java.lang.String COLUMN_OFFER_PRICE = "offer_price";
+    field public static final java.lang.String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
     field public static final java.lang.String COLUMN_POSTER_ART_URI = "poster_art_uri";
     field public static final java.lang.String COLUMN_PREVIEW_DURATION = "preview_duration";
     field public static final java.lang.String COLUMN_PREVIEW_INTENT_URI = "preview_intent_uri";
@@ -23897,20 +24031,52 @@
     field public static final java.lang.String COLUMN_PREVIEW_VIDEO_URI = "preview_video_uri";
     field public static final java.lang.String COLUMN_PREVIEW_WEIGHT = "preview_weight";
     field public static final java.lang.String COLUMN_RECORDING_PROHIBITED = "recording_prohibited";
+    field public static final java.lang.String COLUMN_RELEASE_DATE = "release_date";
+    field public static final java.lang.String COLUMN_REVIEW_RATING = "review_rating";
+    field public static final java.lang.String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
     field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
     field public static final java.lang.String COLUMN_SEASON_DISPLAY_NUMBER = "season_display_number";
     field public static final deprecated java.lang.String COLUMN_SEASON_NUMBER = "season_number";
     field public static final java.lang.String COLUMN_SEASON_TITLE = "season_title";
     field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
+    field public static final java.lang.String COLUMN_STARTING_PRICE = "starting_price";
     field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
+    field public static final java.lang.String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
     field public static final java.lang.String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
     field public static final java.lang.String COLUMN_TITLE = "title";
+    field public static final java.lang.String COLUMN_TYPE = "type";
     field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
     field public static final java.lang.String COLUMN_VIDEO_HEIGHT = "video_height";
     field public static final java.lang.String COLUMN_VIDEO_WIDTH = "video_width";
+    field public static final java.lang.String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program";
     field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
+    field public static final java.lang.String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
+    field public static final java.lang.String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
+    field public static final java.lang.String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
+    field public static final java.lang.String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
+    field public static final java.lang.String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
+    field public static final java.lang.String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
+    field public static final java.lang.String REVIEW_RATING_STYLE_PERCENTAGE = "REVIEW_RATING_STYLE_PERCENTAGE";
+    field public static final java.lang.String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
+    field public static final java.lang.String REVIEW_RATING_STYLE_THUMBS_UP_DOWN = "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
+    field public static final java.lang.String TYPE_ALBUM = "TYPE_ALBUM";
+    field public static final java.lang.String TYPE_ARTIST = "TYPE_ARTIST";
+    field public static final java.lang.String TYPE_CHANNEL = "TYPE_CHANNEL";
+    field public static final java.lang.String TYPE_CLIP = "TYPE_CLIP";
+    field public static final java.lang.String TYPE_EVENT = "TYPE_EVENT";
+    field public static final java.lang.String TYPE_MOVIE = "TYPE_MOVIE";
+    field public static final java.lang.String TYPE_PLAYLIST = "TYPE_PLAYLIST";
+    field public static final java.lang.String TYPE_STATION = "TYPE_STATION";
+    field public static final java.lang.String TYPE_TRACK = "TYPE_TRACK";
+    field public static final java.lang.String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
+    field public static final java.lang.String TYPE_TV_SEASON = "TYPE_TV_SEASON";
+    field public static final java.lang.String TYPE_TV_SERIES = "TYPE_TV_SERIES";
+    field public static final java.lang.String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
+    field public static final java.lang.String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
+    field public static final java.lang.String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
   }
 
   public static final class TvContract.Programs.Genres {
@@ -24021,10 +24187,13 @@
     method public void unregisterCallback(android.media.tv.TvInputManager.TvInputCallback);
     method public void updateTvInputInfo(android.media.tv.TvInputInfo);
     field public static final java.lang.String ACTION_BLOCKED_RATINGS_CHANGED = "android.media.tv.action.BLOCKED_RATINGS_CHANGED";
+    field public static final java.lang.String ACTION_MAKE_CHANNEL_BROWSABLE = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
     field public static final java.lang.String ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED = "android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED";
     field public static final java.lang.String ACTION_QUERY_CONTENT_RATING_SYSTEMS = "android.media.tv.action.QUERY_CONTENT_RATING_SYSTEMS";
     field public static final java.lang.String ACTION_SETUP_INPUTS = "android.media.tv.action.SETUP_INPUTS";
     field public static final java.lang.String ACTION_VIEW_RECORDING_SCHEDULES = "android.media.tv.action.VIEW_RECORDING_SCHEDULES";
+    field public static final java.lang.String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
+    field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
     field public static final int INPUT_STATE_CONNECTED = 0; // 0x0
     field public static final int INPUT_STATE_CONNECTED_STANDBY = 1; // 0x1
     field public static final int INPUT_STATE_DISCONNECTED = 2; // 0x2
@@ -25553,6 +25722,7 @@
     method public java.security.cert.X509Certificate getCaCertificate();
     method public java.security.cert.X509Certificate[] getCaCertificates();
     method public java.security.cert.X509Certificate getClientCertificate();
+    method public java.security.cert.X509Certificate[] getClientCertificateChain();
     method public java.lang.String getDomainSuffixMatch();
     method public int getEapMethod();
     method public java.lang.String getIdentity();
@@ -25566,6 +25736,7 @@
     method public void setCaCertificate(java.security.cert.X509Certificate);
     method public void setCaCertificates(java.security.cert.X509Certificate[]);
     method public void setClientKeyEntry(java.security.PrivateKey, java.security.cert.X509Certificate);
+    method public void setClientKeyEntryWithCertificateChain(java.security.PrivateKey, java.security.cert.X509Certificate[]);
     method public void setDomainSuffixMatch(java.lang.String);
     method public void setEapMethod(int);
     method public void setIdentity(java.lang.String);
@@ -25641,6 +25812,7 @@
     method public boolean isTdlsSupported();
     method public boolean isWifiEnabled();
     method public boolean pingSupplicant();
+    method public void queryPasspointIcon(long, java.lang.String);
     method public boolean reassociate();
     method public boolean reconnect();
     method public boolean removeNetwork(int);
@@ -25651,6 +25823,10 @@
     method public boolean startScan();
     method public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsCallback);
     method public int updateNetwork(android.net.wifi.WifiConfiguration);
+    field public static final java.lang.String ACTION_PASSPOINT_DEAUTH_IMMINENT = "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT";
+    field public static final java.lang.String ACTION_PASSPOINT_ICON = "android.net.wifi.action.PASSPOINT_ICON";
+    field public static final java.lang.String ACTION_PASSPOINT_OSU_PROVIDERS_LIST = "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST";
+    field public static final java.lang.String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION = "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION";
     field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
     field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
     field public static final int ERROR_AUTHENTICATING = 1; // 0x1
@@ -25658,6 +25834,18 @@
     field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
     field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi";
     field public static final java.lang.String EXTRA_NEW_STATE = "newState";
+    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_BSSID = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_BSSID";
+    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_ESS = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_ESS";
+    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REASON_URL = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REASON_URL";
+    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY";
+    field public static final java.lang.String EXTRA_PASSPOINT_ICON_BSSID = "android.net.wifi.extra.PASSPOINT_ICON_BSSID";
+    field public static final java.lang.String EXTRA_PASSPOINT_ICON_DATA = "android.net.wifi.extra.PASSPOINT_ICON_DATA";
+    field public static final java.lang.String EXTRA_PASSPOINT_ICON_FILENAME = "android.net.wifi.extra.PASSPOINT_ICON_FILENAME";
+    field public static final java.lang.String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_BSSID = "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_BSSID";
+    field public static final java.lang.String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_DATA = "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_DATA";
+    field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID";
+    field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD";
+    field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL";
     field public static final java.lang.String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
     field public static final java.lang.String EXTRA_RESULTS_UPDATED = "resultsUpdated";
     field public static final java.lang.String EXTRA_SUPPLICANT_CONNECTED = "connected";
@@ -33648,6 +33836,7 @@
     field public static final java.lang.String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
     field public static final java.lang.String ACTION_MANAGE_APPLICATIONS_SETTINGS = "android.settings.MANAGE_APPLICATIONS_SETTINGS";
     field public static final java.lang.String ACTION_MANAGE_DEFAULT_APPS_SETTINGS = "android.settings.MANAGE_DEFAULT_APPS_SETTINGS";
+    field public static final java.lang.String ACTION_MANAGE_EXTERNAL_SOURCES = "android.settings.action.MANAGE_EXTERNAL_SOURCES";
     field public static final java.lang.String ACTION_MANAGE_OVERLAY_PERMISSION = "android.settings.action.MANAGE_OVERLAY_PERMISSION";
     field public static final java.lang.String ACTION_MANAGE_WRITE_SETTINGS = "android.settings.action.MANAGE_WRITE_SETTINGS";
     field public static final java.lang.String ACTION_MEMORY_CARD_SETTINGS = "android.settings.MEMORY_CARD_SETTINGS";
@@ -33797,7 +33986,7 @@
     field public static final java.lang.String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES = "enabled_notification_policy_access_packages";
     field public static final deprecated java.lang.String HTTP_PROXY = "http_proxy";
     field public static final java.lang.String INPUT_METHOD_SELECTOR_VISIBILITY = "input_method_selector_visibility";
-    field public static final java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
+    field public static final deprecated java.lang.String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
     field public static final java.lang.String LOCATION_MODE = "location_mode";
     field public static final int LOCATION_MODE_BATTERY_SAVING = 2; // 0x2
     field public static final int LOCATION_MODE_HIGH_ACCURACY = 3; // 0x3
@@ -34354,6 +34543,8 @@
 
   public static final class VoicemailContract.Voicemails implements android.provider.BaseColumns android.provider.OpenableColumns {
     method public static android.net.Uri buildSourceUri(java.lang.String);
+    field public static final java.lang.String ARCHIVED = "archived";
+    field public static final java.lang.String BACKED_UP = "backed_up";
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String DATE = "date";
     field public static final java.lang.String DELETED = "deleted";
@@ -34361,6 +34552,7 @@
     field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemails";
     field public static final java.lang.String DURATION = "duration";
     field public static final java.lang.String HAS_CONTENT = "has_content";
+    field public static final java.lang.String IS_OMTP_VOICEMAIL = "is_omtp_voicemail";
     field public static final java.lang.String IS_READ = "is_read";
     field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail";
     field public static final java.lang.String LAST_MODIFIED = "last_modified";
@@ -34368,6 +34560,7 @@
     field public static final java.lang.String NUMBER = "number";
     field public static final java.lang.String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name";
     field public static final java.lang.String PHONE_ACCOUNT_ID = "subscription_id";
+    field public static final java.lang.String RESTORED = "restored";
     field public static final java.lang.String SOURCE_DATA = "source_data";
     field public static final java.lang.String SOURCE_PACKAGE = "source_package";
     field public static final java.lang.String TRANSCRIPTION = "transcription";
@@ -35757,17 +35950,25 @@
     ctor public AutoFillService();
     method public final android.os.IBinder onBind(android.content.Intent);
     method public void onConnected();
+    method public void onDatasetAuthenticationRequest(android.os.Bundle, int);
     method public void onDisconnected();
     method public abstract void onFillRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback);
-    method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.os.CancellationSignal, android.service.autofill.SaveCallback);
+    method public void onFillResponseAuthenticationRequest(android.os.Bundle, int);
+    method public abstract void onSaveRequest(android.app.assist.AssistStructure, android.os.Bundle, android.service.autofill.SaveCallback);
     field public static final java.lang.String EXTRA_DATASET_EXTRAS = "android.service.autofill.extra.DATASET_EXTRAS";
     field public static final java.lang.String EXTRA_RESPONSE_EXTRAS = "android.service.autofill.extra.RESPONSE_EXTRAS";
+    field public static final int FLAG_AUTHENTICATION_ERROR = 4; // 0x4
+    field public static final int FLAG_AUTHENTICATION_REQUESTED = 1; // 0x1
+    field public static final int FLAG_AUTHENTICATION_SUCCESS = 2; // 0x2
+    field public static final int FLAG_FINGERPRINT_AUTHENTICATION_NOT_AVAILABLE = 8; // 0x8
     field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutoFillService";
     field public static final java.lang.String SERVICE_META_DATA = "android.autofill";
   }
 
   public final class FillCallback {
+    method public void onDatasetAuthentication(android.view.autofill.Dataset, int);
     method public void onFailure(java.lang.CharSequence);
+    method public void onFillResponseAuthentication(int);
     method public void onSuccess(android.view.autofill.FillResponse);
   }
 
@@ -38197,6 +38398,7 @@
     field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_STRING = "ci_action_on_sys_update_extra_string";
     field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING = "ci_action_on_sys_update_extra_val_string";
     field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING = "ci_action_on_sys_update_intent_string";
+    field public static final java.lang.String KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING = "config_ims_package_override_string";
     field public static final java.lang.String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool";
     field public static final java.lang.String KEY_DEFAULT_SIM_CALL_MANAGER_STRING = "default_sim_call_manager_string";
     field public static final java.lang.String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string";
@@ -38812,6 +39014,7 @@
     method public int getSimState();
     method public int getSimState(int);
     method public java.lang.String getSubscriberId();
+    method public java.lang.String getVisualVoicemailPackageName(android.telecom.PhoneAccountHandle);
     method public java.lang.String getVoiceMailAlphaTag();
     method public java.lang.String getVoiceMailNumber();
     method public int getVoiceNetworkType();
@@ -38832,6 +39035,7 @@
     method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
     method public boolean isWorldPhone();
     method public void listen(android.telephony.PhoneStateListener, int);
+    method public boolean sendDialerCode(java.lang.String);
     method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
     method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
     method public void sendUssdRequest(java.lang.String, int, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
@@ -38864,6 +39068,7 @@
     field public static final int DATA_DISCONNECTED = 0; // 0x0
     field public static final int DATA_SUSPENDED = 3; // 0x3
     field public static final java.lang.String EXTRA_CALL_VOICEMAIL_INTENT = "android.telephony.extra.CALL_VOICEMAIL_INTENT";
+    field public static final java.lang.String EXTRA_HIDE_PUBLIC_SETTINGS = "android.telephony.extra.HIDE_PUBLIC_SETTINGS";
     field public static final java.lang.String EXTRA_INCOMING_NUMBER = "incoming_number";
     field public static final java.lang.String EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT = "android.telephony.extra.LAUNCH_VOICEMAIL_SETTINGS_INTENT";
     field public static final java.lang.String EXTRA_NOTIFICATION_COUNT = "android.telephony.extra.NOTIFICATION_COUNT";
@@ -38872,6 +39077,7 @@
     field public static final java.lang.String EXTRA_STATE_OFFHOOK;
     field public static final java.lang.String EXTRA_STATE_RINGING;
     field public static final java.lang.String EXTRA_VOICEMAIL_NUMBER = "android.telephony.extra.VOICEMAIL_NUMBER";
+    field public static final java.lang.String METADATA_HIDE_VOICEMAIL_SETTINGS_MENU = "android.telephony.HIDE_VOICEMAIL_SETTINGS_MENU";
     field public static final int NETWORK_TYPE_1xRTT = 7; // 0x7
     field public static final int NETWORK_TYPE_CDMA = 4; // 0x4
     field public static final int NETWORK_TYPE_EDGE = 2; // 0x2
@@ -39566,6 +39772,7 @@
     method public boolean addPermission(android.content.pm.PermissionInfo);
     method public boolean addPermissionAsync(android.content.pm.PermissionInfo);
     method public void addPreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName);
+    method public boolean canRequestPackageInstalls();
     method public java.lang.String[] canonicalToCurrentPackageNames(java.lang.String[]);
     method public int checkPermission(java.lang.String, java.lang.String);
     method public int checkSignatures(java.lang.String, java.lang.String);
@@ -39631,6 +39838,7 @@
     method public android.content.res.XmlResourceParser getXml(java.lang.String, int, android.content.pm.ApplicationInfo);
     method public boolean hasSystemFeature(java.lang.String);
     method public boolean hasSystemFeature(java.lang.String, int);
+    method public boolean isPermissionReviewModeEnabled();
     method public boolean isPermissionRevokedByPolicy(java.lang.String, java.lang.String);
     method public boolean isSafeMode();
     method public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(android.content.Intent, int);
@@ -42718,6 +42926,7 @@
     field public static final int FLAG_PRIVATE = 4; // 0x4
     field public static final int FLAG_ROUND = 16; // 0x10
     field public static final int FLAG_SECURE = 2; // 0x2
+    field public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 32; // 0x20
     field public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1; // 0x1
     field public static final int INVALID_DISPLAY = -1; // 0xffffffff
     field public static final int STATE_DOZE = 3; // 0x3
@@ -42964,6 +43173,7 @@
     field public static final int SOURCE_JOYSTICK = 16777232; // 0x1000010
     field public static final int SOURCE_KEYBOARD = 257; // 0x101
     field public static final int SOURCE_MOUSE = 8194; // 0x2002
+    field public static final int SOURCE_MOUSE_RELATIVE = 131076; // 0x20004
     field public static final int SOURCE_STYLUS = 16386; // 0x4002
     field public static final int SOURCE_TOUCHPAD = 1048584; // 0x100008
     field public static final int SOURCE_TOUCHSCREEN = 4098; // 0x1002
@@ -44120,6 +44330,7 @@
     method public void createContextMenu(android.view.ContextMenu);
     method public void destroyDrawingCache();
     method public android.view.WindowInsets dispatchApplyWindowInsets(android.view.WindowInsets);
+    method public boolean dispatchCapturedPointerEvent(android.view.MotionEvent);
     method public void dispatchConfigurationChanged(android.content.res.Configuration);
     method public void dispatchDisplayHint(int);
     method public boolean dispatchDragEvent(android.view.DragEvent);
@@ -44138,6 +44349,7 @@
     method public boolean dispatchNestedPrePerformAccessibilityAction(int, android.os.Bundle);
     method public boolean dispatchNestedPreScroll(int, int, int[], int[]);
     method public boolean dispatchNestedScroll(int, int, int, int, int[]);
+    method public void dispatchPointerCaptureChanged(boolean);
     method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public void dispatchProvideAutoFillStructure(android.view.ViewStructure, int);
     method public void dispatchProvideStructure(android.view.ViewStructure);
@@ -44289,7 +44501,6 @@
     method public java.lang.Object getTag(int);
     method public int getTextAlignment();
     method public int getTextDirection();
-    method public final deprecated java.lang.CharSequence getTooltip();
     method public final java.lang.CharSequence getTooltipText();
     method public android.view.View getTooltipView();
     method public final int getTop();
@@ -44321,6 +44532,7 @@
     method public boolean hasNestedScrollingParent();
     method public boolean hasOnClickListeners();
     method public boolean hasOverlappingRendering();
+    method public boolean hasPointerCapture();
     method public boolean hasTransientState();
     method public boolean hasWindowFocus();
     method public static android.view.View inflate(android.content.Context, int, android.view.ViewGroup);
@@ -44385,6 +44597,7 @@
     method public android.view.WindowInsets onApplyWindowInsets(android.view.WindowInsets);
     method protected void onAttachedToWindow();
     method public void onCancelPendingInputEvents();
+    method public boolean onCapturedPointerEvent(android.view.MotionEvent);
     method public boolean onCheckIsTextEditor();
     method protected void onConfigurationChanged(android.content.res.Configuration);
     method protected void onCreateContextMenu(android.view.ContextMenu);
@@ -44414,6 +44627,7 @@
     method protected void onLayout(boolean, int, int, int, int);
     method protected void onMeasure(int, int);
     method protected void onOverScrolled(int, int, boolean, boolean);
+    method public void onPointerCaptureChange(boolean);
     method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public void onProvideAutoFillStructure(android.view.ViewStructure, int);
     method public void onProvideAutoFillVirtualStructure(android.view.ViewStructure, int);
@@ -44456,6 +44670,7 @@
     method public void postOnAnimation(java.lang.Runnable);
     method public void postOnAnimationDelayed(java.lang.Runnable, long);
     method public void refreshDrawableState();
+    method public void releasePointerCapture();
     method public boolean removeCallbacks(java.lang.Runnable);
     method public void removeOnAttachStateChangeListener(android.view.View.OnAttachStateChangeListener);
     method public void removeOnLayoutChangeListener(android.view.View.OnLayoutChangeListener);
@@ -44466,6 +44681,7 @@
     method public boolean requestFocus(int, android.graphics.Rect);
     method public final boolean requestFocusFromTouch();
     method public void requestLayout();
+    method public void requestPointerCapture();
     method public boolean requestRectangleOnScreen(android.graphics.Rect);
     method public boolean requestRectangleOnScreen(android.graphics.Rect, boolean);
     method public final void requestUnbufferedDispatch(android.view.MotionEvent);
@@ -44543,6 +44759,7 @@
     method public void setNextFocusRightId(int);
     method public void setNextFocusUpId(int);
     method public void setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener);
+    method public void setOnCapturedPointerListener(android.view.View.OnCapturedPointerListener);
     method public void setOnClickListener(android.view.View.OnClickListener);
     method public void setOnContextClickListener(android.view.View.OnContextClickListener);
     method public void setOnCreateContextMenuListener(android.view.View.OnCreateContextMenuListener);
@@ -44590,7 +44807,6 @@
     method public void setTag(int, java.lang.Object);
     method public void setTextAlignment(int);
     method public void setTextDirection(int);
-    method public final deprecated void setTooltip(java.lang.CharSequence);
     method public final void setTooltipText(java.lang.CharSequence);
     method public final void setTop(int);
     method public void setTouchDelegate(android.view.TouchDelegate);
@@ -44626,8 +44842,8 @@
     field public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0; // 0x0
     field public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 1; // 0x1
     field public static final android.util.Property<android.view.View, java.lang.Float> ALPHA;
-    field public static final int AUTO_FILL_FLAG_TYPE_FILL = 1; // 0x1
-    field public static final int AUTO_FILL_FLAG_TYPE_SAVE = 2; // 0x2
+    field public static final int AUTO_FILL_FLAG_TYPE_FILL = 268435456; // 0x10000000
+    field public static final int AUTO_FILL_FLAG_TYPE_SAVE = 536870912; // 0x20000000
     field public static final int DRAG_FLAG_GLOBAL = 256; // 0x100
     field public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION = 64; // 0x40
     field public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION = 128; // 0x80
@@ -44816,6 +45032,10 @@
     method public abstract void onViewDetachedFromWindow(android.view.View);
   }
 
+  public static abstract interface View.OnCapturedPointerListener {
+    method public abstract boolean onCapturedPointer(android.view.View, android.view.MotionEvent);
+  }
+
   public static abstract interface View.OnClickListener {
     method public abstract void onClick(android.view.View);
   }
@@ -45552,6 +45772,7 @@
     method public abstract boolean onMenuItemSelected(int, android.view.MenuItem);
     method public abstract boolean onMenuOpened(int, android.view.Menu);
     method public abstract void onPanelClosed(int, android.view.Menu);
+    method public default void onPointerCaptureChanged(boolean);
     method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
     method public default void onProvideKeyboardShortcuts(java.util.List<android.view.KeyboardShortcutGroup>, android.view.Menu, int);
     method public abstract boolean onSearchRequested();
@@ -46561,6 +46782,8 @@
   public static final class Dataset.Builder {
     ctor public Dataset.Builder(java.lang.CharSequence);
     method public android.view.autofill.Dataset build();
+    method public android.view.autofill.Dataset.Builder requiresCustomAuthentication(android.os.Bundle, int);
+    method public android.view.autofill.Dataset.Builder requiresFingerprintAuthentication(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.Bundle, int);
     method public android.view.autofill.Dataset.Builder setExtras(android.os.Bundle);
     method public android.view.autofill.Dataset.Builder setValue(android.view.autofill.AutoFillId, android.view.autofill.AutoFillValue);
   }
@@ -46576,6 +46799,8 @@
     method public android.view.autofill.FillResponse.Builder addDataset(android.view.autofill.Dataset);
     method public android.view.autofill.FillResponse.Builder addSavableFields(android.view.autofill.AutoFillId...);
     method public android.view.autofill.FillResponse build();
+    method public android.view.autofill.FillResponse.Builder requiresCustomAuthentication(android.os.Bundle, int);
+    method public android.view.autofill.FillResponse.Builder requiresFingerprintAuthentication(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.Bundle, int);
     method public android.view.autofill.FillResponse.Builder setExtras(android.os.Bundle);
   }
 
@@ -49370,6 +49595,7 @@
     method public android.graphics.PorterDuff.Mode getSecondaryProgressTintMode();
     method public final synchronized void incrementProgressBy(int);
     method public final synchronized void incrementSecondaryProgressBy(int);
+    method public boolean isAnimating();
     method public synchronized boolean isIndeterminate();
     method public void onRestoreInstanceState(android.os.Parcelable);
     method public android.os.Parcelable onSaveInstanceState();
diff --git a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiObject.java b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiObject.java
index 751bbe8..ef6d55f 100644
--- a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiObject.java
+++ b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/UiObject.java
@@ -808,7 +808,7 @@
      *
      * @return Rect
      * @throws UiObjectNotFoundException
-     * @see {@link #getBounds()}
+     * @see #getBounds()
      * @since API Level 17
      */
     public Rect getVisibleBounds() throws UiObjectNotFoundException {
diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java
index d98b4ff..71561c3 100644
--- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java
+++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java
@@ -40,7 +40,7 @@
      * actions such as dialing 911 or posting messages to public forums, etc.
      *
      * @param isSet True to set as monkey test. False to set as regular functional test (default).
-     * @see {@link ActivityManager#isUserAMonkey()}
+     * @see ActivityManager#isUserAMonkey()
      */
     public void setRunAsMonkey(boolean isSet) {
         IActivityManager am = ActivityManager.getService();
diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java
index c9e09e4..87e512c 100644
--- a/core/java/android/accounts/AbstractAccountAuthenticator.java
+++ b/core/java/android/accounts/AbstractAccountAuthenticator.java
@@ -707,7 +707,7 @@
      * @param account the account to clone, will never be null
      * @return a Bundle result or null if the result is to be returned via the response.
      * @throws NetworkErrorException
-     * @see {@link #addAccountFromCredentials(AccountAuthenticatorResponse, Account, Bundle)}
+     * @see #addAccountFromCredentials(AccountAuthenticatorResponse, Account, Bundle)
      */
     public Bundle getAccountCredentialsForCloning(final AccountAuthenticatorResponse response,
             final Account account) throws NetworkErrorException {
@@ -732,7 +732,7 @@
      * provided by {@link #getAccountCredentialsForCloning(AccountAuthenticatorResponse, Account)}.
      * @return a Bundle result or null if the result is to be returned via the response.
      * @throws NetworkErrorException
-     * @see {@link #getAccountCredentialsForCloning(AccountAuthenticatorResponse, Account)}
+     * @see #getAccountCredentialsForCloning(AccountAuthenticatorResponse, Account)
      */
     public Bundle addAccountFromCredentials(final AccountAuthenticatorResponse response,
             Account account,
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index b27fa24..def0ff9 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -53,9 +53,12 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.SuppressWarnings;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.ExecutionException;
@@ -864,11 +867,17 @@
      *
      * @param account The account for which visibility data should be returned.
      *
-     * @return Map from uid to visibility for given account
+     * @return Map from uid to visibility for given account.
      */
     public Map<Integer, Integer> getUidsAndVisibilityForAccount(Account account) {
-        // TODO implement.
-        return null;
+        try {
+            @SuppressWarnings("unchecked")
+            Map<Integer, Integer> result = (Map<Integer, Integer>) mService
+                    .getUidsAndVisibilityForAccount(account);
+            return result;
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -2110,10 +2119,23 @@
                 synchronized (mAccountsUpdatedListeners) {
                     try {
                         if (mAccountsUpdatedListeners.containsKey(listener)) {
-                            listener.onAccountsUpdated(accountsCopy);
+                            Set<String> types = mAccountsUpdatedListenersTypes.get(listener);
+                            if (types != null) {
+                                // filter by account type;
+                                ArrayList<Account> filtered = new ArrayList<>();
+                                for (Account account : accountsCopy) {
+                                    if (types.contains(account.type)) {
+                                        filtered.add(account);
+                                    }
+                                }
+                                listener.onAccountsUpdated(
+                                        filtered.toArray(new Account[filtered.size()]));
+                            } else {
+                                listener.onAccountsUpdated(accountsCopy);
+                            }
                         }
                     } catch (SQLException e) {
-                        // Better luck next time.  If the problem was disk-full,
+                        // Better luck next time. If the problem was disk-full,
                         // the STORAGE_OK intent will re-trigger the update.
                         Log.e(TAG, "Can't update accounts", e);
                     }
@@ -2759,6 +2781,9 @@
     private final HashMap<OnAccountsUpdateListener, Handler> mAccountsUpdatedListeners =
             Maps.newHashMap();
 
+    private final HashMap<OnAccountsUpdateListener, Set<String> > mAccountsUpdatedListenersTypes =
+            Maps.newHashMap();
+
     /**
      * BroadcastReceiver that listens for the LOGIN_ACCOUNTS_CHANGED_ACTION intent
      * so that it can read the updated list of accounts and send them to the listener
@@ -2784,7 +2809,7 @@
      * accounts of any type related to the caller. This method is equivalent to
      * addOnAccountsUpdatedListener(listener, handler, updateImmediately, null)
      *
-     * @see #addOnAccountsUpdatedListener(OnAccountsUpdateListener, Handler, boolean, Handler,
+     * @see #addOnAccountsUpdatedListener(OnAccountsUpdateListener, Handler, boolean,
      *      String[])
      */
     public void addOnAccountsUpdatedListener(final OnAccountsUpdateListener listener,
@@ -2828,7 +2853,10 @@
             final boolean wasEmpty = mAccountsUpdatedListeners.isEmpty();
 
             mAccountsUpdatedListeners.put(listener, handler);
-
+            if (accountTypes != null) {
+                mAccountsUpdatedListenersTypes.put(listener,
+                        new HashSet<String>(Arrays.asList(accountTypes)));
+            }
 
             if (wasEmpty) {
                 // Register a broadcast receiver to monitor account changes
@@ -2870,6 +2898,7 @@
                 return;
             }
             mAccountsUpdatedListeners.remove(listener);
+            mAccountsUpdatedListenersTypes.remove(listener);
             if (mAccountsUpdatedListeners.isEmpty()) {
                 mContext.unregisterReceiver(mAccountsChangedBroadcastReceiver);
             }
diff --git a/core/java/android/accounts/ChooseAccountActivity.java b/core/java/android/accounts/ChooseAccountActivity.java
index 242b3ea..16a45ba 100644
--- a/core/java/android/accounts/ChooseAccountActivity.java
+++ b/core/java/android/accounts/ChooseAccountActivity.java
@@ -52,7 +52,9 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-
+        // TODO This activity is only used by getAuthTokenByFeatures and can not see
+        // VISIBILITY_USER_MANAGED_NOT_VISIBLE accounts. It should be moved to account managed
+        // service.
         mAccounts = getIntent().getParcelableArrayExtra(AccountManager.KEY_ACCOUNTS);
         mAccountManagerResponse =
                 getIntent().getParcelableExtra(AccountManager.KEY_ACCOUNT_MANAGER_RESPONSE);
diff --git a/core/java/android/accounts/ChooseTypeAndAccountActivity.java b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
index 8c71f50..95fdfef 100644
--- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java
+++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
@@ -40,7 +40,9 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -110,7 +112,7 @@
     private static final String KEY_INSTANCE_STATE_EXISTING_ACCOUNTS = "existingAccounts";
     private static final String KEY_INSTANCE_STATE_SELECTED_ACCOUNT_NAME = "selectedAccountName";
     private static final String KEY_INSTANCE_STATE_SELECTED_ADD_ACCOUNT = "selectedAddAccount";
-    private static final String KEY_INSTANCE_STATE_ACCOUNT_LIST = "accountList";
+    private static final String KEY_INSTANCE_STATE_ACCOUNT_LIST = "accountAndVisibilityList";
 
     private static final int SELECTED_ITEM_NONE = -1;
 
@@ -120,7 +122,11 @@
     private boolean mSelectedAddNewAccount = false;
     private String mDescriptionOverride;
 
-    private ArrayList<Account> mAccounts;
+    private Map<Account, Integer> mAccounts;
+    // TODO Redesign flow to show NOT_VISIBLE accounts
+    // and display a warning if they are selected.
+    // Currently NOT_VISBILE accounts are not shown at all.
+    private ArrayList<Account> mPossiblyVisibleAccounts;
     private int mPendingRequest = REQUEST_NULL;
     private Parcelable[] mExistingAccounts = null;
     private int mSelectedItemIndex;
@@ -164,12 +170,12 @@
                     savedInstanceState.getParcelableArray(KEY_INSTANCE_STATE_EXISTING_ACCOUNTS);
 
             // Makes sure that any user selection is preserved across orientation changes.
-            mSelectedAccountName = savedInstanceState.getString(
-                    KEY_INSTANCE_STATE_SELECTED_ACCOUNT_NAME);
-
-            mSelectedAddNewAccount = savedInstanceState.getBoolean(
-                    KEY_INSTANCE_STATE_SELECTED_ADD_ACCOUNT, false);
-            mAccounts = savedInstanceState.getParcelableArrayList(KEY_INSTANCE_STATE_ACCOUNT_LIST);
+            mSelectedAccountName =
+                    savedInstanceState.getString(KEY_INSTANCE_STATE_SELECTED_ACCOUNT_NAME);
+            mSelectedAddNewAccount =
+                    savedInstanceState.getBoolean(KEY_INSTANCE_STATE_SELECTED_ADD_ACCOUNT, false);
+            mAccounts = (Map<Account, Integer>) savedInstanceState
+                    .getSerializable(KEY_INSTANCE_STATE_ACCOUNT_LIST);
         } else {
             mPendingRequest = REQUEST_NULL;
             mExistingAccounts = null;
@@ -220,9 +226,15 @@
             }
         }
 
-        String[] listItems = getListOfDisplayableOptions(mAccounts);
-        mSelectedItemIndex = getItemIndexToSelect(
-            mAccounts, mSelectedAccountName, mSelectedAddNewAccount);
+        mPossiblyVisibleAccounts = new ArrayList<>(mAccounts.size());
+        for (Map.Entry<Account, Integer> entry : mAccounts.entrySet()) {
+            if (AccountManager.VISIBILITY_NOT_VISIBLE != entry.getValue()) {
+                mPossiblyVisibleAccounts.add(entry.getKey());
+            }
+        }
+        String[] listItems = getListOfDisplayableOptions(mPossiblyVisibleAccounts);
+        mSelectedItemIndex = getItemIndexToSelect(mPossiblyVisibleAccounts, mSelectedAccountName,
+                mSelectedAddNewAccount);
 
         super.onCreate(savedInstanceState);
         setContentView(R.layout.choose_type_and_account);
@@ -250,15 +262,18 @@
             outState.putParcelableArray(KEY_INSTANCE_STATE_EXISTING_ACCOUNTS, mExistingAccounts);
         }
         if (mSelectedItemIndex != SELECTED_ITEM_NONE) {
-            if (mSelectedItemIndex == mAccounts.size()) {
+            if (mSelectedItemIndex == mPossiblyVisibleAccounts.size()) {
                 outState.putBoolean(KEY_INSTANCE_STATE_SELECTED_ADD_ACCOUNT, true);
             } else {
                 outState.putBoolean(KEY_INSTANCE_STATE_SELECTED_ADD_ACCOUNT, false);
                 outState.putString(KEY_INSTANCE_STATE_SELECTED_ACCOUNT_NAME,
-                        mAccounts.get(mSelectedItemIndex).name);
+                        mPossiblyVisibleAccounts.get(mSelectedItemIndex).name);
             }
         }
-        outState.putParcelableArrayList(KEY_INSTANCE_STATE_ACCOUNT_LIST, mAccounts);
+        // should be HashMap by default.
+        HashMap<Account, Integer> accountsHashMap = (mAccounts instanceof HashMap)
+                ? (HashMap) mAccounts : new HashMap<Account, Integer>(mAccounts);
+        outState.putSerializable(KEY_INSTANCE_STATE_ACCOUNT_LIST, accountsHashMap);
     }
 
     public void onCancelButtonClicked(View view) {
@@ -266,11 +281,11 @@
     }
 
     public void onOkButtonClicked(View view) {
-        if (mSelectedItemIndex == mAccounts.size()) {
+        if (mSelectedItemIndex == mPossiblyVisibleAccounts.size()) {
             // Selected "Add New Account" option
             startChooseAccountTypeActivity();
         } else if (mSelectedItemIndex != SELECTED_ITEM_NONE) {
-            onAccountSelected(mAccounts.get(mSelectedItemIndex));
+            onAccountSelected(mPossiblyVisibleAccounts.get(mSelectedItemIndex));
         }
     }
 
@@ -321,6 +336,7 @@
                 }
 
                 if (accountName == null || accountType == null) {
+                    // new account was added.
                     Account[] currentAccounts = AccountManager.get(this).getAccountsForPackage(
                             mCallingPackage, mCallingUid);
                     Set<Account> preExistingAccounts = new HashSet<Account>();
@@ -328,6 +344,7 @@
                         preExistingAccounts.add((Account) accountParcel);
                     }
                     for (Account account : currentAccounts) {
+                        // New account is visible to the app - return it.
                         if (!preExistingAccounts.contains(account)) {
                             accountName = account.name;
                             accountType = account.type;
@@ -409,13 +426,27 @@
     }
 
     private void setResultAndFinish(final String accountName, final String accountType) {
+        // Mark account as visible since user chose it.
+        Account account = new Account(accountName, accountType);
+        Integer oldVisibility = mAccounts.get(account);
+        // oldVisibility is null if new account was added
+        if (oldVisibility == null) {
+            Map<Account, Integer> accountsAndVisibility = AccountManager.get(this)
+                    .getAccountsAndVisibilityForPackage(mCallingPackage, null /* type */);
+            oldVisibility = accountsAndVisibility.get(account);
+        }
+        if (oldVisibility != null
+                && oldVisibility == AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE) {
+            AccountManager.get(this).setAccountVisibility(account, mCallingUid,
+                    AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
+        }
         Bundle bundle = new Bundle();
         bundle.putString(AccountManager.KEY_ACCOUNT_NAME, accountName);
         bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, accountType);
         setResult(Activity.RESULT_OK, new Intent().putExtras(bundle));
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "ChooseTypeAndAccountActivity.setResultAndFinish: "
-                    + "selected account " + accountName + ", " + accountType);
+            Log.v(TAG, "ChooseTypeAndAccountActivity.setResultAndFinish: selected account "
+                    + accountName + ", " + accountType);
         }
         finish();
     }
@@ -474,25 +505,28 @@
     }
 
     /**
-     * Create a list of Account objects for each account that is acceptable. Filter out
-     * accounts that don't match the allowable types, if provided, or that don't match the
-     * allowable accounts, if provided.
+     * Create a list of Account objects for each account that is acceptable. Filter out accounts
+     * that don't match the allowable types, if provided, or that don't match the allowable
+     * accounts, if provided.
      */
-    private ArrayList<Account> getAcceptableAccountChoices(AccountManager accountManager) {
-      final Account[] accounts = accountManager.getAccountsForPackage(mCallingPackage,
-              mCallingUid);
-      ArrayList<Account> accountsToPopulate = new ArrayList<Account>(accounts.length);
-      for (Account account : accounts) {
-          if (mSetOfAllowableAccounts != null && !mSetOfAllowableAccounts.contains(account)) {
-              continue;
-          }
-          if (mSetOfRelevantAccountTypes != null
-                  && !mSetOfRelevantAccountTypes.contains(account.type)) {
-              continue;
-          }
-          accountsToPopulate.add(account);
-      }
-      return accountsToPopulate;
+    private Map<Account, Integer> getAcceptableAccountChoices(AccountManager accountManager) {
+        Map<Account, Integer> accountsAndVisibility =
+                accountManager.getAccountsAndVisibilityForPackage(mCallingPackage, null /* type */);
+
+        Map<Account, Integer> accountsToPopulate =
+                new HashMap<Account, Integer>(accountsAndVisibility.size());
+        for (Map.Entry<Account, Integer> entry : accountsAndVisibility.entrySet()) {
+            if (mSetOfAllowableAccounts != null
+                    && !mSetOfAllowableAccounts.contains(entry.getKey())) {
+                continue;
+            }
+            if (mSetOfRelevantAccountTypes != null
+                    && !mSetOfRelevantAccountTypes.contains(entry.getKey().type)) {
+                continue;
+            }
+            accountsToPopulate.put(entry.getKey(), entry.getValue());
+        }
+        return accountsToPopulate;
     }
 
     /**
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl
index 66c3ca3..63a0919 100644
--- a/core/java/android/accounts/IAccountManager.aidl
+++ b/core/java/android/accounts/IAccountManager.aidl
@@ -108,8 +108,8 @@
     void isCredentialsUpdateSuggested(in IAccountManagerResponse response, in Account account,
         String statusToken);
 
-    /* Allows Authenticator to get UIDs of packages which registered to receive updates about given account type.*/
-    int[] getRequestingUidsForType(String accountType);
+    /* Returns Map<Integer, Integer> from UID to visibility with all values stored for given account*/
+    Map getUidsAndVisibilityForAccount(in Account account);
 
     boolean addAccountExplicitlyWithVisibility(in Account account, String password, in Bundle extras,
             in Map visibility);
@@ -117,7 +117,7 @@
     boolean setAccountVisibility(in Account a, int uid, int newVisibility);
     int getAccountVisibility(in Account a, int uid);
 
-    /* Type may be null  returns Map <Account, Integer>*/
+    /* Type may be null returns Map <Account, Integer>*/
     Map getAccountsAndVisibilityForPackage(in String packageName, in String accountType);
 
     /* Check if the package in a user can access an account */
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index 634dc1fd..08ad976 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -469,8 +469,9 @@
      */
     @Override
     public boolean doAnimationFrame(long frameTime) {
-        // TODO: Need to find a better signal than this
-        return getDuration() + getStartDelay() >= frameTime;
+        // TODO: Need to find a better signal than this. There's a bug in SystemUI that's preventing
+        // returning !isStarted() from working.
+        return false;
     }
 
     /**
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index d5814a3..8aba405 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -174,6 +174,19 @@
      */
     private long mPauseTime = -1;
 
+    // This is to work around a bug in b/34736819. This needs to be removed once app team
+    // fixes their side.
+    private AnimatorListenerAdapter mDummyListener = new AnimatorListenerAdapter() {
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            if (mNodeMap.get(animation) == null) {
+                throw new AndroidRuntimeException("Error: animation ended is not in the node map");
+            }
+            mNodeMap.get(animation).mEnded = true;
+
+        }
+    };
+
     public AnimatorSet() {
         super();
         mNodeMap.put(mDelayAnim, mRootNode);
@@ -1018,6 +1031,8 @@
     }
 
     private void startAnimation() {
+        addDummyListener();
+
         // Register animation callback
         addAnimationCallback(mStartDelay);
 
@@ -1062,6 +1077,20 @@
         }
     }
 
+    // This is to work around the issue in b/34736819, as the old behavior in AnimatorSet had
+    // masked a real bug in play movies. TODO: remove this and below once the root cause is fixed.
+    private void addDummyListener() {
+        for (int i = 1; i < mNodes.size(); i++) {
+            mNodes.get(i).mAnimation.addListener(mDummyListener);
+        }
+    }
+
+    private void removeDummyListener() {
+        for (int i = 1; i < mNodes.size(); i++) {
+            mNodes.get(i).mAnimation.removeListener(mDummyListener);
+        }
+    }
+
     private int findLatestEventIdForTime(long currentPlayTime) {
         int size = mEvents.size();
         int latestId = mLastEventId;
@@ -1107,6 +1136,7 @@
                 tmpListeners.get(i).onAnimationEnd(this, mReversing);
             }
         }
+        removeDummyListener();
         mSelfPulse = true;
         mReversing = false;
     }
@@ -1151,6 +1181,17 @@
         anim.mNodeMap = new ArrayMap<Animator, Node>();
         anim.mNodes = new ArrayList<Node>(nodeCount);
         anim.mEvents = new ArrayList<AnimationEvent>();
+        anim.mDummyListener = new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                if (anim.mNodeMap.get(animation) == null) {
+                    throw new AndroidRuntimeException("Error: animation ended is not in the node"
+                            + " map");
+                }
+                anim.mNodeMap.get(animation).mEnded = true;
+
+            }
+        };
         anim.mReversing = false;
         anim.mDependencyDirty = true;
 
@@ -1333,7 +1374,7 @@
         // Sort the list of events in ascending order of their time
         // Create the list including the delay animation.
         mEvents.clear();
-        for (int i = 0; i < mNodes.size(); i++) {
+        for (int i = 1; i < mNodes.size(); i++) {
             Node node = mNodes.get(i);
             mEvents.add(new AnimationEvent(node, AnimationEvent.ANIMATION_START));
             mEvents.add(new AnimationEvent(node, AnimationEvent.ANIMATION_DELAY_ENDED));
@@ -1345,13 +1386,15 @@
                 long t1 = e1.getTime();
                 long t2 = e2.getTime();
                 if (t1 == t2) {
-                    if (e1.mNode == e2.mNode) {
-                        // For the same animation, start event has to happen before end.
+                    // For events that happen at the same time, we need them to be in the sequence
+                    // (end, start, start delay ended)
+                    if (e2.mEvent + e1.mEvent == AnimationEvent.ANIMATION_START
+                            + AnimationEvent.ANIMATION_DELAY_ENDED) {
+                        // Ensure start delay happens after start
                         return e1.mEvent - e2.mEvent;
+                    } else {
+                        return e2.mEvent - e1.mEvent;
                     }
-                    // For different animation, end events need to happen before start, to ensure
-                    // sequential animations finish the previous one before starting the next one.
-                    return e2.mEvent - e1.mEvent;
                 }
                 if (t2 == DURATION_INFINITE) {
                     return -1;
@@ -1364,22 +1407,83 @@
             }
         });
 
+        int eventSize = mEvents.size();
+        // For the same animation, start event has to happen before end.
+        for (int i = 0; i < eventSize;) {
+            AnimationEvent event = mEvents.get(i);
+            if (event.mEvent == AnimationEvent.ANIMATION_END) {
+                boolean needToSwapStart;
+                if (event.mNode.mStartTime == event.mNode.mEndTime) {
+                    needToSwapStart = true;
+                } else if (event.mNode.mEndTime == event.mNode.mStartTime
+                        + event.mNode.mAnimation.getStartDelay()) {
+                    // Swapping start delay
+                    needToSwapStart = false;
+                } else {
+                    i++;
+                    continue;
+                }
+
+                int startEventId = eventSize;
+                int startDelayEndId = eventSize;
+                for (int j = i + 1; j < eventSize; j++) {
+                    if (startEventId < eventSize && startDelayEndId < eventSize) {
+                        break;
+                    }
+                    if (mEvents.get(j).mNode == event.mNode) {
+                        if (mEvents.get(j).mEvent == AnimationEvent.ANIMATION_START) {
+                            // Found start event
+                            startEventId = j;
+                        } else if (mEvents.get(j).mEvent == AnimationEvent.ANIMATION_DELAY_ENDED) {
+                            startDelayEndId = j;
+                        }
+                    }
+
+                }
+                if (needToSwapStart && startEventId == mEvents.size()) {
+                    throw new UnsupportedOperationException("Something went wrong, no start is"
+                            + "found after stop for an animation that has the same start and end"
+                            + "time.");
+
+                }
+                if (startDelayEndId == mEvents.size()) {
+                    throw new UnsupportedOperationException("Something went wrong, no start"
+                            + "delay end is found after stop for an animation");
+
+                }
+
+                // We need to make sure start is inserted before start delay ended event,
+                // because otherwise inserting start delay ended events first would change
+                // the start event index.
+                if (needToSwapStart) {
+                    AnimationEvent startEvent = mEvents.remove(startEventId);
+                    mEvents.add(i, startEvent);
+                    i++;
+                }
+
+                AnimationEvent startDelayEndEvent = mEvents.remove(startDelayEndId);
+                mEvents.add(i, startDelayEndEvent);
+                i += 2;
+            } else {
+                i++;
+            }
+        }
+
+        if (!mEvents.isEmpty() && mEvents.get(0).mEvent != AnimationEvent.ANIMATION_START) {
+            throw new UnsupportedOperationException(
+                    "Sorting went bad, the start event should always be at index 0");
+        }
+
+        // Add AnimatorSet's start delay node to the beginning
+        mEvents.add(0, new AnimationEvent(mRootNode, AnimationEvent.ANIMATION_START));
+        mEvents.add(1, new AnimationEvent(mRootNode, AnimationEvent.ANIMATION_DELAY_ENDED));
+        mEvents.add(2, new AnimationEvent(mRootNode, AnimationEvent.ANIMATION_END));
+
         if (mEvents.get(mEvents.size() - 1).mEvent == AnimationEvent.ANIMATION_START
                 || mEvents.get(mEvents.size() - 1).mEvent == AnimationEvent.ANIMATION_DELAY_ENDED) {
             throw new UnsupportedOperationException(
                     "Something went wrong, the last event is not an end event");
         }
-        if (mEvents.get(1).mEvent != AnimationEvent.ANIMATION_DELAY_ENDED
-                || mEvents.get(1).mNode != mRootNode) {
-            throw new UnsupportedOperationException(
-                    "Sorting went bad, the root node's start delay end event should always be at"
-                            + " index 1");
-        }
-        if (mEvents.get(2).mEvent != AnimationEvent.ANIMATION_END
-                || mEvents.get(2).mNode != mRootNode) {
-            throw new UnsupportedOperationException(
-                    "Sorting went bad, the start delay end event should always be at index 2");
-        }
     }
 
     /**
diff --git a/core/java/android/annotation/FontRes.java b/core/java/android/annotation/FontRes.java
new file mode 100644
index 0000000..dbacb58
--- /dev/null
+++ b/core/java/android/annotation/FontRes.java
@@ -0,0 +1,37 @@
+/*
+ * 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.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+/**
+ * Denotes that an integer parameter, field or method return value is expected
+ * to be a Font resource reference (e.g. R.font.myfont).
+ *
+ * @hide
+ */
+@Documented
+@Retention(SOURCE)
+@Target({METHOD, PARAMETER, FIELD})
+public @interface FontRes {
+}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index df4c4af..6f95309 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -117,9 +117,8 @@
 import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.autofill.AutoFillId;
-import android.view.autofill.Dataset;
-import android.view.autofill.DatasetField;
-import android.view.autofill.VirtualViewDelegate;
+import android.view.autofill.AutoFillManager;
+import android.view.autofill.AutoFillSession;
 import android.widget.AdapterView;
 import android.widget.Toast;
 import android.widget.Toolbar;
@@ -848,10 +847,7 @@
     private boolean mHasCurrentPermissionsRequest;
 
     @GuardedBy("this")
-    private WeakReference<IAutoFillAppCallback> mAutoFillCallback;
-
-    @GuardedBy("this")
-    private VirtualViewDelegate.Callback mAutoFillDelegateCallback;
+    private AutoFillSession mAutoFillSession;
 
     private static native String getDlWarning();
 
@@ -1704,76 +1700,17 @@
     }
 
     /**
-     * Lazily sets the {@link #mAutoFillDelegateCallback}.
-     */
-    private void setAutoFillDelegateCallback() {
-        synchronized (this) {
-            if (mAutoFillDelegateCallback == null) {
-                mAutoFillDelegateCallback = new VirtualViewDelegate.Callback() {
-                    // TODO(b/33197203): implement
-                };
-            }
-        }
-    }
-
-    /**
      * Lazily gets the {@link IAutoFillAppCallback} for this activitity.
      *
      * <p>This callback is used by the {@link AutoFillService} app to auto-fill the activity fields.
      */
-    WeakReference<IAutoFillAppCallback> getAutoFillCallback() {
+    IAutoFillAppCallback getAutoFillCallback() {
         synchronized (this) {
-            if (mAutoFillCallback == null) {
-                final IAutoFillAppCallback cb = new IAutoFillAppCallback.Stub() {
-                    @Override
-                    public void autoFill(Dataset dataset) throws RemoteException {
-                        // TODO(b/33197203): must keep the dataset so subsequent calls pass the same
-                        // dataset.extras to service
-                        runOnUiThread(() -> {
-                            final View root = getWindow().getDecorView().getRootView();
-                            for (DatasetField field : dataset.getFields()) {
-                                final AutoFillId id = field.getId();
-                                if (id == null) {
-                                    Log.w(TAG, "autoFill(): null id on " + field);
-                                    continue;
-                                }
-                                final int viewId = id.getViewId();
-                                final View view = root.findViewByAccessibilityIdTraversal(viewId);
-                                if (view == null) {
-                                    Log.w(TAG, "autoFill(): no View with id " + viewId);
-                                    continue;
-                                }
-
-                                // TODO(b/33197203): handle protected value (like credit card)
-                                if (id.isVirtual()) {
-                                    // Delegate virtual fields to provider.
-                                    setAutoFillDelegateCallback();
-                                    final VirtualViewDelegate mgr = view
-                                            .getAutoFillVirtualViewDelegate(
-                                                    mAutoFillDelegateCallback);
-                                    if (mgr == null) {
-                                        Log.w(TAG, "autoFill(): cannot fill virtual " + id
-                                                + "; no auto-fill provider for view "
-                                                + view.getClass());
-                                        continue;
-                                    }
-                                    if (DEBUG_AUTO_FILL) {
-                                        Log.d(TAG, "autoFill(): delegating " + id
-                                                + " to virtual manager  " + mgr);
-                                    }
-                                    mgr.autoFill(id.getVirtualChildId(), field.getValue());
-                                } else {
-                                    // Handle non-virtual fields itself.
-                                    view.autoFill(field.getValue());
-                                }
-                            }
-                        });
-                    }
-                };
-                mAutoFillCallback = new WeakReference<IAutoFillAppCallback>(cb);
+            if (mAutoFillSession == null) {
+                mAutoFillSession = new AutoFillSession(this);
             }
+            return mAutoFillSession.getCallback();
         }
-        return mAutoFillCallback;
     }
 
     /**
@@ -4330,7 +4267,7 @@
      * @param requestCode If >= 0, this code will be returned in
      *                    onActivityResult() when the activity exits.
      * @param options Additional options for how the Activity should be started.
-     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     * See {@link android.content.Context#startActivity(Intent, Bundle)}
      * Context.startActivity(Intent, Bundle)} for more details.
      *
      * @throws android.content.ActivityNotFoundException
@@ -4389,6 +4326,18 @@
         }
     }
 
+    /**
+     * Returns whether there are any activity transitions currently running on this
+     * activity. A return value of {@code true} can mean that either an enter or
+     * exit transition is running, including whether the background of the activity
+     * is animating as a part of that transition.
+     *
+     * @return true if a transition is currently running on this activity, false otherwise.
+     */
+    public boolean isActivityTransitionRunning() {
+        return mActivityTransitionState.isTransitionRunning();
+    }
+
     private Bundle transferSpringboardActivityOptions(Bundle options) {
         if (options == null && (mWindow != null && !mWindow.isActive())) {
             final ActivityOptions activityOptions = getActivityOptions();
@@ -4539,7 +4488,7 @@
      * <var>flagsMask</var>
      * @param extraFlags Always set to 0.
      * @param options Additional options for how the Activity should be started.
-     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     * See {@link android.content.Context#startActivity(Intent, Bundle)}
      * Context.startActivity(Intent, Bundle)} for more details.  If options
      * have also been supplied by the IntentSender, options given here will
      * override any that conflict with those given by the IntentSender.
@@ -4624,7 +4573,7 @@
      *
      * @param intent The intent to start.
      * @param options Additional options for how the Activity should be started.
-     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     * See {@link android.content.Context#startActivity(Intent, Bundle)}
      * Context.startActivity(Intent, Bundle)} for more details.
      *
      * @throws android.content.ActivityNotFoundException
@@ -4673,7 +4622,7 @@
      *
      * @param intents The intents to start.
      * @param options Additional options for how the Activity should be started.
-     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     * See {@link android.content.Context#startActivity(Intent, Bundle)}
      * Context.startActivity(Intent, Bundle)} for more details.
      *
      * @throws android.content.ActivityNotFoundException
@@ -4722,7 +4671,7 @@
      * <var>flagsMask</var>
      * @param extraFlags Always set to 0.
      * @param options Additional options for how the Activity should be started.
-     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     * See {@link android.content.Context#startActivity(Intent, Bundle)}
      * Context.startActivity(Intent, Bundle)} for more details.  If options
      * have also been supplied by the IntentSender, options given here will
      * override any that conflict with those given by the IntentSender.
@@ -4782,7 +4731,7 @@
      *         onActivityResult() when the activity exits, as described in
      *         {@link #startActivityForResult}.
      * @param options Additional options for how the Activity should be started.
-     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     * See {@link android.content.Context#startActivity(Intent, Bundle)}
      * Context.startActivity(Intent, Bundle)} for more details.
      *
      * @return If a new activity was launched then true is returned; otherwise
@@ -4859,7 +4808,7 @@
      * your own activity; the only changes you can make are to the extras
      * inside of it.
      * @param options Additional options for how the Activity should be started.
-     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     * See {@link android.content.Context#startActivity(Intent, Bundle)}
      * Context.startActivity(Intent, Bundle)} for more details.
      *
      * @return Returns a boolean indicating whether there was another Activity
@@ -4914,7 +4863,7 @@
      * @param intent The intent to start.
      * @param requestCode Reply request code.  < 0 if reply is not requested.
      * @param options Additional options for how the Activity should be started.
-     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     * See {@link android.content.Context#startActivity(Intent, Bundle)}
      * Context.startActivity(Intent, Bundle)} for more details.
      *
      * @throws android.content.ActivityNotFoundException
@@ -4967,7 +4916,7 @@
      * @param intent The intent to start.
      * @param requestCode Reply request code.  < 0 if reply is not requested.
      * @param options Additional options for how the Activity should be started.
-     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     * See {@link android.content.Context#startActivity(Intent, Bundle)}
      * Context.startActivity(Intent, Bundle)} for more details.
      *
      * @throws android.content.ActivityNotFoundException
@@ -6067,9 +6016,9 @@
             getWindow().peekDecorView().getViewRootImpl().dump(prefix, fd, writer, args);
         }
 
-        if (mAutoFillCallback != null) {
-            writer.print(prefix); writer.print("mAutoFillCallback: " );
-                    writer.println(mAutoFillCallback.get());
+        if (mAutoFillSession!= null) {
+            writer.print(prefix); writer.print("mAutoFillSession: " );
+                    writer.println(mAutoFillSession);
         }
 
         mHandler.getLooper().dump(new PrintWriterPrinter(writer), prefix);
@@ -7161,7 +7110,7 @@
      *
      * @return True if caption is displayed on content, false if it pushes the content down.
      *
-     * @see {@link #setOverlayWithDecorCaptionEnabled(boolean)}
+     * @see #setOverlayWithDecorCaptionEnabled(boolean)
      */
     public boolean isOverlayWithDecorCaptionEnabled() {
         return mWindow.isOverlayWithDecorCaptionEnabled();
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 3902bd6..b367d0c 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -133,7 +133,7 @@
     public final static boolean ENABLE_TASK_SNAPSHOTS;
 
     static {
-        ENABLE_TASK_SNAPSHOTS = SystemProperties.getBoolean("persist.enable_task_snapshots", false);
+        ENABLE_TASK_SNAPSHOTS = SystemProperties.getBoolean("persist.enable_task_snapshots", true);
     }
 
     static final class UidObserver extends IUidObserver.Stub {
@@ -2340,13 +2340,13 @@
         public static final int FLAG_FOREGROUND = 1<<1;
 
         /**
-         * Bit for {@link #flags): set if the service is running in a
+         * Bit for {@link #flags}: set if the service is running in a
          * core system process.
          */
         public static final int FLAG_SYSTEM_PROCESS = 1<<2;
 
         /**
-         * Bit for {@link #flags): set if the service is running in a
+         * Bit for {@link #flags}: set if the service is running in a
          * persistent process.
          */
         public static final int FLAG_PERSISTENT_PROCESS = 1<<3;
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 89510d9..e848080 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -154,6 +154,12 @@
     public abstract List<IBinder> getTopVisibleActivities();
 
     /**
+     * Returns the top, focused activity of the currently visible stack, but only if it belongs to
+     * the given UID.
+     */
+    public abstract IBinder getTopVisibleActivity(int uid);
+
+    /**
      * Callback for window manager to let activity manager know that docked stack changes its
      * minimized state.
      */
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 34eaa0b..cf20b68 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -541,6 +541,7 @@
         ParcelFileDescriptor profileFd;
         int samplingInterval;
         boolean autoStopProfiler;
+        boolean streamingOutput;
         boolean profiling;
         boolean handlingProfiling;
         public void setProfiler(ProfilerInfo profilerInfo) {
@@ -566,6 +567,7 @@
             profileFd = fd;
             samplingInterval = profilerInfo.samplingInterval;
             autoStopProfiler = profilerInfo.autoStopProfiler;
+            streamingOutput = profilerInfo.streamingOutput;
         }
         public void startProfiling() {
             if (profileFd == null || profiling) {
@@ -574,7 +576,8 @@
             try {
                 int bufferSize = SystemProperties.getInt("debug.traceview-buffer-size-mb", 8);
                 VMDebug.startMethodTracing(profileFile, profileFd.getFileDescriptor(),
-                        bufferSize * 1024 * 1024, 0, samplingInterval != 0, samplingInterval);
+                        bufferSize * 1024 * 1024, 0, samplingInterval != 0, samplingInterval,
+                        streamingOutput);
                 profiling = true;
             } catch (RuntimeException e) {
                 Slog.w(TAG, "Profiling failed on path " + profileFile);
@@ -2964,7 +2967,7 @@
                 if (!forAutoFill) {
                     r.activity.onProvideAssistContent(content);
                 } else if (addAutoFillCallback) {
-                    IAutoFillAppCallback cb = r.activity.getAutoFillCallback().get();
+                    IAutoFillAppCallback cb = r.activity.getAutoFillCallback();
                     if (cb != null) {
                         data.putBinder(AutoFillService.KEY_CALLBACK, cb.asBinder());
                     } else {
@@ -5029,7 +5032,9 @@
      * @hide
      */
     public void stopProfiling() {
-        mProfiler.stopProfiling();
+        if (mProfiler != null) {
+            mProfiler.stopProfiling();
+        }
     }
 
     static final void handleDumpHeap(boolean managed, DumpHeapData dhd) {
@@ -5275,6 +5280,7 @@
             mProfiler.profileFd = data.initProfilerInfo.profileFd;
             mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval;
             mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler;
+            mProfiler.streamingOutput = data.initProfilerInfo.streamingOutput;
         }
 
         // send up app name; do this *before* waiting for debugger
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index af41db0..1eaf029 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -208,6 +208,7 @@
     private ArrayList<Matrix> mSharedElementParentMatrices;
     private boolean mSharedElementTransitionComplete;
     private boolean mViewsTransitionComplete;
+    private boolean mBackgroundAnimatorComplete;
     private ArrayList<View> mStrippedTransitioningViews = new ArrayList<>();
 
     public ActivityTransitionCoordinator(Window window,
@@ -884,6 +885,10 @@
         startInputWhenTransitionsComplete();
     }
 
+    protected void backgroundAnimatorComplete() {
+        mBackgroundAnimatorComplete = true;
+    }
+
     protected void sharedElementTransitionComplete() {
         mSharedElementTransitionComplete = true;
         startInputWhenTransitionsComplete();
@@ -966,6 +971,11 @@
         }
     }
 
+    public boolean isTransitionRunning() {
+        return !(mViewsTransitionComplete && mSharedElementTransitionComplete &&
+                mBackgroundAnimatorComplete);
+    }
+
     private static class FixedEpicenterCallback extends Transition.EpicenterCallback {
         private Rect mEpicenter;
 
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java
index f2616ff..b8f5a8e 100644
--- a/core/java/android/app/ActivityTransitionState.java
+++ b/core/java/android/app/ActivityTransitionState.java
@@ -336,6 +336,26 @@
         }
     }
 
+    public boolean isTransitionRunning() {
+        // Note that *only* enter *or* exit will be running at any given time
+        if (mEnterTransitionCoordinator != null) {
+            if (mEnterTransitionCoordinator.isTransitionRunning()) {
+                return true;
+            }
+        }
+        if (mCalledExitCoordinator != null) {
+            if (mCalledExitCoordinator.isTransitionRunning()) {
+                return true;
+            }
+        }
+        if (mReturnExitCoordinator != null) {
+            if (mReturnExitCoordinator.isTransitionRunning()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     public void startExitOutTransition(Activity activity, Bundle options) {
         mEnterTransitionCoordinator = null;
         if (!activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS) ||
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index f790542..2c2b279 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -310,6 +310,12 @@
     }
 
     @Override
+    public boolean isPermissionReviewModeEnabled() {
+        return mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_permissionReviewRequired);
+    }
+
+    @Override
     public PermissionGroupInfo getPermissionGroupInfo(String name,
             int flags) throws NameNotFoundException {
         try {
@@ -2580,4 +2586,13 @@
             return false;
         }
     }
+
+    @Override
+    public boolean canRequestPackageInstalls() {
+        try {
+            return mPM.canRequestPackageInstalls(mContext.getPackageName(), mContext.getUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
 }
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index b569b79..0454acb 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -587,6 +587,7 @@
                     @Override
                     public void onAnimationEnd(Animator animation) {
                         makeOpaque();
+                        backgroundAnimatorComplete();
                     }
                 });
                 mBackgroundAnimator.start();
@@ -598,9 +599,13 @@
                         makeOpaque();
                     }
                 });
+                backgroundAnimatorComplete();
             } else {
                 makeOpaque();
+                backgroundAnimatorComplete();
             }
+        } else {
+            backgroundAnimatorComplete();
         }
     }
 
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index 2672798..f04eef2 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -201,6 +201,7 @@
 
     public void startExit() {
         if (!mIsExitStarted) {
+            backgroundAnimatorComplete();
             mIsExitStarted = true;
             pauseInput();
             ViewGroup decorView = getDecor();
@@ -303,11 +304,13 @@
                             mIsBackgroundReady = true;
                             notifyComplete();
                         }
+                        backgroundAnimatorComplete();
                     }
                 });
                 mBackgroundAnimator.setDuration(getFadeDuration());
                 mBackgroundAnimator.start();
             } else {
+                backgroundAnimatorComplete();
                 mIsBackgroundReady = true;
             }
         }
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 62d6898..612998d 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -762,6 +762,24 @@
      * are going to call back with {@link #onActivityResult(int, int, Intent)}.
      */
     public void setTargetFragment(Fragment fragment, int requestCode) {
+        // Don't allow a caller to set a target fragment in another FragmentManager,
+        // but there's a snag: people do set target fragments before fragments get added.
+        // We'll have the FragmentManager check that for validity when we move
+        // the fragments to a valid state.
+        final FragmentManager mine = getFragmentManager();
+        final FragmentManager theirs = fragment.getFragmentManager();
+        if (mine != null && theirs != null && mine != theirs) {
+            throw new IllegalArgumentException("Fragment " + fragment
+                    + " must share the same FragmentManager to be set as a target fragment");
+        }
+
+        // Don't let someone create a cycle.
+        for (Fragment check = fragment; check != null; check = check.getTargetFragment()) {
+            if (check == this) {
+                throw new IllegalArgumentException("Setting " + fragment + " as the target of "
+                        + this + " would create a target cycle");
+            }
+        }
         mTarget = fragment;
         mTargetRequestCode = requestCode;
     }
@@ -1114,7 +1132,7 @@
      *
      * @param intent The intent to start.
      * @param options Additional options for how the Activity should be started.
-     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     * See {@link android.content.Context#startActivity(Intent, Bundle)}
      * Context.startActivity(Intent, Bundle)} for more details.
      */
     public void startActivity(Intent intent, Bundle options) {
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 44f1322..32cf1c3 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1110,10 +1110,25 @@
                                 }
                             }
                         }
+
                         f.mHost = mHost;
                         f.mParentFragment = mParent;
                         f.mFragmentManager = mParent != null
                                 ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();
+
+                        // If we have a target fragment, push it along to at least CREATED
+                        // so that this one can rely on it as an initialized dependency.
+                        if (f.mTarget != null) {
+                            if (!mActive.contains(f.mTarget)) {
+                                throw new IllegalStateException("Fragment " + f
+                                        + " declared target fragment " + f.mTarget
+                                        + " that does not belong to this FragmentManager!");
+                            }
+                            if (f.mTarget.mState < Fragment.CREATED) {
+                                moveToState(f.mTarget, Fragment.CREATED, 0, 0, true);
+                            }
+                        }
+
                         dispatchOnFragmentPreAttached(f, mHost.getContext(), false);
                         f.mCalled = false;
                         f.onAttach(mHost.getContext());
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 5a48793..0a2f804 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -539,7 +539,7 @@
      */
     void swapDockedAndFullscreenStack();
     void notifyLockedProfile(int userId);
-    void startConfirmDeviceCredentialIntent(in Intent intent);
+    void startConfirmDeviceCredentialIntent(in Intent intent, in Bundle options);
     void sendIdleJobTrigger();
     int sendIntentSender(in IIntentSender target, int code, in Intent intent,
             in String resolvedType, in IIntentReceiver finishedReceiver,
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 740af9c..58cd310 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -54,7 +54,9 @@
     boolean areNotificationsEnabled(String pkg);
     int getPackageImportance(String pkg);
 
+    void createNotificationChannelGroups(String pkg, in ParceledListSlice channelGroupList);
     void createNotificationChannels(String pkg, in ParceledListSlice channelsList);
+    ParceledListSlice getNotificationChannelGroupsForPackage(String pkg, int uid, boolean includeDeleted);
     void updateNotificationChannelForPackage(String pkg, int uid, in NotificationChannel channel);
     NotificationChannel getNotificationChannel(String pkg, String channelId);
     NotificationChannel getNotificationChannelForPackage(String pkg, int uid, String channelId, boolean includeDeleted);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index b4fe6b8..80f4985 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -71,7 +71,6 @@
 import com.android.internal.R;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.NotificationColorUtil;
-import com.android.internal.util.Preconditions;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -982,6 +981,12 @@
     public static final String EXTRA_HISTORIC_MESSAGES = "android.messages.historic";
 
     /**
+     * {@link #extras} key: whether the notification should be colorized as
+     * supplied to {@link Builder#setColorized(boolean)}}.
+     */
+    public static final String EXTRA_COLORIZED = "android.colorized";
+
+    /**
      * {@link #extras} key: the user that built the notification.
      *
      * @hide
@@ -2438,6 +2443,8 @@
         private ArrayList<Action> mActions = new ArrayList<Action>(MAX_ACTION_BUTTONS);
         private ArrayList<String> mPersonList = new ArrayList<String>();
         private NotificationColorUtil mColorUtil;
+        private boolean mIsLegacy;
+        private boolean mIsLegacyInitialized;
         private boolean mColorUtilInited = false;
 
         /**
@@ -2456,6 +2463,10 @@
          * so make sure to call {@link StandardTemplateParams#reset()} before using it.
          */
         StandardTemplateParams mParams = new StandardTemplateParams();
+        private int mTextColorsAreForBackground = COLOR_INVALID;
+        private int mPrimaryTextColor = COLOR_INVALID;
+        private int mSecondaryTextColor = COLOR_INVALID;
+        private int mActionBarColor = COLOR_INVALID;
 
         /**
          * Constructs a new Builder with the defaults:
@@ -2475,9 +2486,23 @@
          *            A {@link Context} that will be used by the Builder to construct the
          *            RemoteViews. The Context will not be held past the lifetime of this Builder
          *            object.
+         * @param channelId
+         *            The constructed Notification will be posted on this
+         *            {@link NotificationChannel}. To use a NotificationChannel, it must first be
+         *            created using {@link NotificationManager#createNotificationChannel}.
          */
+        public Builder(Context context, String channelId) {
+            this(context, (Notification) null);
+            mN.mChannelId = channelId;
+        }
+
+        /**
+         * @deprecated use {@link Notification.Builder#Notification.Builder(Context, String)}
+         * instead. All posted Notifications must specify a NotificationChannel Id.
+         */
+        @Deprecated
         public Builder(Context context) {
-            this(context, null);
+            this(context, (Notification) null);
         }
 
         /**
@@ -2540,7 +2565,7 @@
         private NotificationColorUtil getColorUtil() {
             if (!mColorUtilInited) {
                 mColorUtilInited = true;
-                if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.LOLLIPOP) {
+                if (isLegacy() || isColorized()) {
                     mColorUtil = NotificationColorUtil.getInstance(mContext);
                 }
             }
@@ -3025,6 +3050,22 @@
         }
 
         /**
+         * Set whether this notification should be colorized. When set, the color set with
+         * {@link #setColor(int)} will be used as the background color of this notification.
+         * <p>
+         * The coloring will only be applied if the notification is ongoing.
+         * This should only be used for high priority ongoing tasks like navigation, an ongoing
+         * call, or other similarly high-priority events for the user.
+         *
+         * @see Builder#setOngoing(boolean)
+         * @see Builder#setColor(int)
+         */
+        public Builder setColorized(boolean colorize) {
+            mN.extras.putBoolean(EXTRA_COLORIZED, colorize);
+            return this;
+        }
+
+        /**
          * Set this flag if you would only like the sound, vibrate
          * and ticker to be played if the notification is not already showing.
          *
@@ -3389,6 +3430,10 @@
             if (profileBadge != null) {
                 contentView.setImageViewBitmap(R.id.profile_badge, profileBadge);
                 contentView.setViewVisibility(R.id.profile_badge, View.VISIBLE);
+                if (isColorized()) {
+                    contentView.setDrawableParameters(R.id.profile_badge, false, -1,
+                            getPrimaryTextColor(), PorterDuff.Mode.SRC_ATOP, -1);
+                }
             }
         }
 
@@ -3446,13 +3491,16 @@
             resetStandardTemplate(contentView);
 
             final Bundle ex = mN.extras;
-
+            updateBackgroundColor(contentView);
             bindNotificationHeader(contentView, p.ambient);
             bindLargeIcon(contentView);
             boolean showProgress = handleProgressBar(p.hasProgress, contentView, ex);
             if (p.title != null) {
                 contentView.setViewVisibility(R.id.title, View.VISIBLE);
                 contentView.setTextViewText(R.id.title, p.title);
+                if (!p.ambient) {
+                    setTextViewColorPrimary(contentView, R.id.title);
+                }
                 contentView.setViewLayoutWidth(R.id.title, showProgress
                         ? ViewGroup.LayoutParams.WRAP_CONTENT
                         : ViewGroup.LayoutParams.MATCH_PARENT);
@@ -3461,6 +3509,9 @@
                 int textId = showProgress ? com.android.internal.R.id.text_line_1
                         : com.android.internal.R.id.text;
                 contentView.setTextViewText(textId, p.text);
+                if (!p.ambient) {
+                    setTextViewColorSecondary(contentView, textId);
+                }
                 contentView.setViewVisibility(textId, View.VISIBLE);
             }
 
@@ -3469,6 +3520,52 @@
             return contentView;
         }
 
+        private void setTextViewColorPrimary(RemoteViews contentView, int id) {
+            ensureColors();
+            contentView.setTextColor(id, mPrimaryTextColor);
+        }
+
+        private int getPrimaryTextColor() {
+            ensureColors();
+            return mPrimaryTextColor;
+        }
+
+        private int getActionBarColor() {
+            ensureColors();
+            return mActionBarColor;
+        }
+
+        private void setTextViewColorSecondary(RemoteViews contentView, int id) {
+            ensureColors();
+            contentView.setTextColor(id, mSecondaryTextColor);
+        }
+
+        private void ensureColors() {
+            int backgroundColor = getBackgroundColor();
+            if (mPrimaryTextColor == COLOR_INVALID
+                    || mSecondaryTextColor == COLOR_INVALID
+                    || mActionBarColor == COLOR_INVALID
+                    || mTextColorsAreForBackground != backgroundColor) {
+                mTextColorsAreForBackground = backgroundColor;
+                mPrimaryTextColor = NotificationColorUtil.resolvePrimaryColor(
+                        mContext, backgroundColor);
+                mSecondaryTextColor = NotificationColorUtil.resolveSecondaryColor(
+                        mContext, backgroundColor);
+                mActionBarColor = NotificationColorUtil.resolveActionBarColor(backgroundColor);
+            }
+        }
+
+        private void updateBackgroundColor(RemoteViews contentView) {
+            if (isColorized()) {
+                contentView.setInt(R.id.status_bar_latest_event_content, "setBackgroundColor",
+                        getBackgroundColor());
+            } else {
+                // Clear it!
+                contentView.setInt(R.id.status_bar_latest_event_content, "setBackgroundResource",
+                        0);
+            }
+        }
+
         /**
          * @param remoteView the remote view to update the minheight in
          * @param hasMinHeight does it have a mimHeight
@@ -3535,15 +3632,17 @@
         }
 
         private void bindExpandButton(RemoteViews contentView) {
-            contentView.setDrawableParameters(R.id.expand_button, false, -1, resolveContrastColor(),
+            int color = isColorized() ? getPrimaryTextColor() : resolveContrastColor();
+            contentView.setDrawableParameters(R.id.expand_button, false, -1, color,
                     PorterDuff.Mode.SRC_ATOP, -1);
             contentView.setInt(R.id.notification_header, "setOriginalNotificationColor",
-                    resolveContrastColor());
+                    color);
         }
 
         private void bindHeaderChronometerAndTime(RemoteViews contentView) {
             if (showsTimeOrChronometer()) {
                 contentView.setViewVisibility(R.id.time_divider, View.VISIBLE);
+                setTextViewColorSecondary(contentView, R.id.time_divider);
                 if (mN.extras.getBoolean(EXTRA_SHOW_CHRONOMETER)) {
                     contentView.setViewVisibility(R.id.chronometer, View.VISIBLE);
                     contentView.setLong(R.id.chronometer, "setBase",
@@ -3551,9 +3650,11 @@
                     contentView.setBoolean(R.id.chronometer, "setStarted", true);
                     boolean countsDown = mN.extras.getBoolean(EXTRA_CHRONOMETER_COUNT_DOWN);
                     contentView.setChronometerCountDown(R.id.chronometer, countsDown);
+                    setTextViewColorSecondary(contentView, R.id.chronometer);
                 } else {
                     contentView.setViewVisibility(R.id.time, View.VISIBLE);
                     contentView.setLong(R.id.time, "setTime", mN.when);
+                    setTextViewColorSecondary(contentView, R.id.time);
                 }
             } else {
                 // We still want a time to be set but gone, such that we can show and hide it
@@ -3576,8 +3677,10 @@
             if (headerText != null) {
                 // TODO: Remove the span entirely to only have the string with propper formating.
                 contentView.setTextViewText(R.id.header_text, processLegacyText(headerText));
+                setTextViewColorSecondary(contentView, R.id.header_text);
                 contentView.setViewVisibility(R.id.header_text, View.VISIBLE);
                 contentView.setViewVisibility(R.id.header_text_divider, View.VISIBLE);
+                setTextViewColorSecondary(contentView, R.id.header_text_divider);
             }
         }
 
@@ -3616,8 +3719,12 @@
         }
         private void bindHeaderAppName(RemoteViews contentView, boolean ambient) {
             contentView.setTextViewText(R.id.app_name_text, loadHeaderAppName());
-            contentView.setTextColor(R.id.app_name_text,
-                    ambient ? resolveAmbientColor() : resolveContrastColor());
+            if (isColorized() && !ambient) {
+                setTextViewColorPrimary(contentView, R.id.app_name_text);
+            } else {
+                contentView.setTextColor(R.id.app_name_text,
+                        ambient ? resolveAmbientColor() : resolveContrastColor());
+            }
         }
 
         private void bindSmallIcon(RemoteViews contentView, boolean ambient) {
@@ -3675,6 +3782,11 @@
                 big.setViewVisibility(R.id.actions, View.VISIBLE);
                 if (p.ambient) {
                     big.setInt(R.id.actions, "setBackgroundColor", Color.TRANSPARENT);
+                } else if (isColorized()) {
+                    big.setInt(R.id.actions, "setBackgroundColor", getActionBarColor());
+                } else {
+                    big.setInt(R.id.actions, "setBackgroundColor", mContext.getColor(
+                            R.color.notification_action_list));
                 }
                 big.setViewLayoutMarginBottomDimen(R.id.notification_action_list_margin_target,
                         R.dimen.notification_action_list_height);
@@ -3696,15 +3808,18 @@
                     && replyText.length > 0 && !TextUtils.isEmpty(replyText[0])) {
                 big.setViewVisibility(R.id.notification_material_reply_container, View.VISIBLE);
                 big.setTextViewText(R.id.notification_material_reply_text_1, replyText[0]);
+                setTextViewColorSecondary(big, R.id.notification_material_reply_text_1);
 
                 if (replyText.length > 1 && !TextUtils.isEmpty(replyText[1])) {
                     big.setViewVisibility(R.id.notification_material_reply_text_2, View.VISIBLE);
                     big.setTextViewText(R.id.notification_material_reply_text_2, replyText[1]);
+                    setTextViewColorSecondary(big, R.id.notification_material_reply_text_2);
 
                     if (replyText.length > 2 && !TextUtils.isEmpty(replyText[2])) {
                         big.setViewVisibility(
                                 R.id.notification_material_reply_text_3, View.VISIBLE);
                         big.setTextViewText(R.id.notification_material_reply_text_3, replyText[2]);
+                        setTextViewColorSecondary(big, R.id.notification_material_reply_text_3);
                     }
                 }
             }
@@ -3930,6 +4045,7 @@
             if (action.mRemoteInputs != null) {
                 button.setRemoteInputs(R.id.action0, action.mRemoteInputs);
             }
+            // TODO: handle emphasized mode / actions right
             if (emphazisedMode) {
                 // change the background bgColor
                 int bgColor = mContext.getColor(oddAction ? R.color.notification_action_list
@@ -3945,16 +4061,19 @@
                     title = ensureColorSpanContrast(title, bgColor, outResultColor);
                 }
                 button.setTextViewText(R.id.action0, title);
+                setTextViewColorPrimary(button, R.id.action0);
                 if (outResultColor != null && outResultColor[0] != null) {
                     // We need to set the text color as well since changing a text to uppercase
                     // clears its spans.
                     button.setTextColor(R.id.action0, outResultColor[0]);
-                } else if (mN.color != COLOR_DEFAULT) {
+                } else if (mN.color != COLOR_DEFAULT && !isColorized()) {
                     button.setTextColor(R.id.action0,resolveContrastColor());
                 }
             } else {
                 button.setTextViewText(R.id.action0, processLegacyText(action.title));
-                if (mN.color != COLOR_DEFAULT) {
+                if (isColorized() && !ambient) {
+                    setTextViewColorPrimary(button, R.id.action0);
+                } else if (mN.color != COLOR_DEFAULT) {
                     button.setTextColor(R.id.action0,
                             ambient ? resolveAmbientColor() : resolveContrastColor());
                 }
@@ -4073,11 +4192,16 @@
          *         doesn't create material notifications by itself) app.
          */
         private boolean isLegacy() {
-            return getColorUtil() != null;
+            if (!mIsLegacyInitialized) {
+                mIsLegacy = mContext.getApplicationInfo().targetSdkVersion
+                        < Build.VERSION_CODES.LOLLIPOP;
+                mIsLegacyInitialized = true;
+            }
+            return mIsLegacy;
         }
 
         private CharSequence processLegacyText(CharSequence charSequence) {
-            if (isLegacy()) {
+            if (isLegacy() || isColorized()) {
                 return getColorUtil().invertCharSequenceColors(charSequence);
             } else {
                 return charSequence;
@@ -4339,6 +4463,37 @@
         private int getActionTombstoneLayoutResource() {
             return R.layout.notification_material_action_tombstone;
         }
+
+        private int getBackgroundColor() {
+            if (isColorized()) {
+                return mN.color;
+            } else {
+                return COLOR_DEFAULT;
+            }
+        }
+
+        private boolean isColorized() {
+            return mN.isColorized();
+        }
+    }
+
+    /**
+     * @return whether this notification is ongoing and can't be dismissed by the user.
+     */
+    private boolean isOngoing() {
+        final int ongoingFlags = Notification.FLAG_FOREGROUND_SERVICE
+                | Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;
+        return (flags & ongoingFlags) != 0;
+    }
+
+    /**
+     * @return true if this notification is colorized. This also factors in wheather the
+     * notification is ongoing.
+     *
+     * @hide
+     */
+    public boolean isColorized() {
+        return extras.getBoolean(EXTRA_COLORIZED) && isOngoing();
     }
 
     private boolean hasLargeIcon() {
@@ -4672,6 +4827,7 @@
             RemoteViews contentView = getStandardView(mBuilder.getBigPictureLayoutResource());
             if (mSummaryTextSet) {
                 contentView.setTextViewText(R.id.text, mBuilder.processLegacyText(mSummaryText));
+                mBuilder.setTextViewColorSecondary(contentView, R.id.text);
                 contentView.setViewVisibility(R.id.text, View.VISIBLE);
             }
             mBuilder.setContentMinHeight(contentView, mBuilder.mN.hasLargeIcon());
@@ -4827,6 +4983,7 @@
         static void applyBigTextContentView(Builder builder,
                 RemoteViews contentView, CharSequence bigTextText) {
             contentView.setTextViewText(R.id.big_text, bigTextText);
+            builder.setTextViewColorSecondary(contentView, R.id.big_text);
             contentView.setViewVisibility(R.id.big_text,
                     TextUtils.isEmpty(bigTextText) ? View.GONE : View.VISIBLE);
             contentView.setInt(R.id.big_text, "setMaxLines", calculateMaxLines(builder));
@@ -5070,7 +5227,7 @@
                     : (m == null) ? null : m.mSender;
             CharSequence text = (m == null)
                     ? null
-                    : mConversationTitle != null ? makeMessageLine(m) : m.mText;
+                    : mConversationTitle != null ? makeMessageLine(m, mBuilder) : m.mText;
 
             return mBuilder.applyStandardTemplateWithActions(mBuilder.getBaseLayoutResource(),
                     mBuilder.mParams.reset().hasProgress(false).title(title).text(text));
@@ -5108,7 +5265,7 @@
                 CharSequence text;
                 if (hasTitle) {
                     bigTitle = title;
-                    text = makeMessageLine(mMessages.get(0));
+                    text = makeMessageLine(mMessages.get(0), mBuilder);
                 } else {
                     bigTitle = mMessages.get(0).mSender;
                     text = mMessages.get(0).mText;
@@ -5146,7 +5303,7 @@
                 Message m = mHistoricMessages.get(firstHistoricMessage + i);
                 int rowId = rowIds[i];
 
-                contentView.setTextViewText(rowId, makeMessageLine(m));
+                contentView.setTextViewText(rowId, makeMessageLine(m, mBuilder));
 
                 if (contractedMessage == m) {
                     contractedChildId = rowId;
@@ -5161,7 +5318,8 @@
                 int rowId = rowIds[i];
 
                 contentView.setViewVisibility(rowId, View.VISIBLE);
-                contentView.setTextViewText(rowId, makeMessageLine(m));
+                contentView.setTextViewText(rowId, makeMessageLine(m, mBuilder));
+                mBuilder.setTextViewColorSecondary(contentView, rowId);
 
                 if (contractedMessage == m) {
                     contractedChildId = rowId;
@@ -5183,17 +5341,22 @@
             return contentView;
         }
 
-        private CharSequence makeMessageLine(Message m) {
+        private CharSequence makeMessageLine(Message m, Builder builder) {
             BidiFormatter bidi = BidiFormatter.getInstance();
             SpannableStringBuilder sb = new SpannableStringBuilder();
+            boolean colorize = builder.isColorized();
             if (TextUtils.isEmpty(m.mSender)) {
                 CharSequence replyName = mUserDisplayName == null ? "" : mUserDisplayName;
                 sb.append(bidi.unicodeWrap(replyName),
-                        makeFontColorSpan(mBuilder.resolveContrastColor()),
+                        makeFontColorSpan(colorize
+                                ? builder.getPrimaryTextColor()
+                                : mBuilder.resolveContrastColor()),
                         0 /* flags */);
             } else {
                 sb.append(bidi.unicodeWrap(m.mSender),
-                        makeFontColorSpan(Color.BLACK),
+                        makeFontColorSpan(colorize
+                                ? builder.getPrimaryTextColor()
+                                : Color.BLACK),
                         0 /* flags */);
             }
             CharSequence text = m.mText == null ? "" : m.mText;
@@ -5212,7 +5375,7 @@
                     : (m == null) ? null : m.mSender;
             CharSequence text = (m == null)
                     ? null
-                    : mConversationTitle != null ? makeMessageLine(m) : m.mText;
+                    : mConversationTitle != null ? makeMessageLine(m, mBuilder) : m.mText;
 
             return mBuilder.applyStandardTemplateWithActions(mBuilder.getBigBaseLayoutResource(),
                     mBuilder.mParams.reset().hasProgress(false).title(title).text(text));
@@ -5503,6 +5666,7 @@
                 if (!TextUtils.isEmpty(str)) {
                     contentView.setViewVisibility(rowIds[i], View.VISIBLE);
                     contentView.setTextViewText(rowIds[i], mBuilder.processLegacyText(str));
+                    mBuilder.setTextViewColorSecondary(contentView, rowIds[i]);
                     contentView.setViewPadding(rowIds[i], 0, topPadding, 0, 0);
                     handleInboxImageMargin(contentView, rowIds[i], first);
                     if (first) {
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index be5f80a..58ff496 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -21,6 +21,8 @@
 import org.xmlpull.v1.XmlSerializer;
 
 import android.annotation.SystemApi;
+import android.app.NotificationManager;
+import android.media.AudioAttributes;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -49,13 +51,17 @@
     private static final String ATT_VISIBILITY = "visibility";
     private static final String ATT_IMPORTANCE = "importance";
     private static final String ATT_LIGHTS = "lights";
+    //TODO: add support for light colors
+    private static final String ATT_LIGHT_COLOR = "light_color";
     private static final String ATT_VIBRATION = "vibration";
     private static final String ATT_VIBRATION_ENABLED = "vibration_enabled";
     private static final String ATT_SOUND = "sound";
-    //TODO: add audio attributes support
-    private static final String ATT_AUDIO_ATTRIBUTES = "audio_attributes";
+    private static final String ATT_USAGE = "usage";
+    private static final String ATT_FLAGS = "flags";
+    private static final String ATT_CONTENT_TYPE = "content_type";
     private static final String ATT_SHOW_BADGE = "show_badge";
     private static final String ATT_USER_LOCKED = "locked";
+    private static final String ATT_GROUP = "group";
     private static final String DELIMITER = ",";
 
     /**
@@ -105,6 +111,12 @@
      * @hide
      */
     @SystemApi
+    public static final int USER_LOCKED_AUDIO_ATTRIBUTES = 0x00000100;
+
+    /**
+     * @hide
+     */
+    @SystemApi
     public static final int[] LOCKABLE_FIELDS = new int[] {
             USER_LOCKED_PRIORITY,
             USER_LOCKED_VISIBILITY,
@@ -113,7 +125,8 @@
             USER_LOCKED_VIBRATION,
             USER_LOCKED_SOUND,
             USER_LOCKED_ALLOWED,
-            USER_LOCKED_SHOW_BADGE
+            USER_LOCKED_SHOW_BADGE,
+            USER_LOCKED_AUDIO_ATTRIBUTES
     };
 
 
@@ -136,6 +149,8 @@
     private boolean mVibrationEnabled;
     private boolean mShowBadge = DEFAULT_SHOW_BADGE;
     private boolean mDeleted = DEFAULT_DELETED;
+    private String mGroup;
+    private AudioAttributes mAudioAttributes = Notification.AUDIO_ATTRIBUTES_DEFAULT;
 
     /**
      * Creates a notification channel.
@@ -173,6 +188,12 @@
         mVibrationEnabled = in.readByte() != 0;
         mShowBadge = in.readByte() != 0;
         mDeleted = in.readByte() != 0;
+        if (in.readByte() != 0) {
+            mGroup = in.readString();
+        } else {
+            mGroup = null;
+        }
+        mAudioAttributes = in.readInt() > 0 ? AudioAttributes.CREATOR.createFromParcel(in) : null;
     }
 
     @Override
@@ -199,6 +220,18 @@
         dest.writeByte(mVibrationEnabled ? (byte) 1 : (byte) 0);
         dest.writeByte(mShowBadge ? (byte) 1 : (byte) 0);
         dest.writeByte(mDeleted ? (byte) 1 : (byte) 0);
+        if (mGroup != null) {
+            dest.writeByte((byte) 1);
+            dest.writeString(mGroup);
+        } else {
+            dest.writeByte((byte) 0);
+        }
+        if (mAudioAttributes != null) {
+            dest.writeInt(1);
+            mAudioAttributes.writeToParcel(dest, 0);
+        } else {
+            dest.writeInt(0);
+        }
     }
 
     /**
@@ -255,6 +288,21 @@
     // Modifiable by apps on channel creation.
 
     /**
+     * Sets what group this channel belongs to.
+     *
+     * Group information is only used for presentation, not for behavior.
+     *
+     * Only modifiable before the channel is submitted to
+     * {@link NotificationManager#notify(String, int, Notification)}.
+     *
+     * @param groupId the id of a group created by
+     * {@link NotificationManager#createNotificationChannelGroup(NotificationChannelGroup)}.
+     */
+    public void setGroup(String groupId) {
+        this.mGroup = groupId;
+    }
+
+    /**
      * Sets whether notifications posted to this channel can appear as application icon badges
      * in a Launcher.
      *
@@ -265,18 +313,23 @@
     }
 
     /**
-     * Sets the sound that should be played for notifications posted to this channel if
-     * the notifications don't supply a sound. Only modifiable before the channel is submitted
-     * to the NotificationManager.
+     * Sets the sound that should be played for notifications posted to this channel and its
+     * audio attributes.
+     *
+     * Only modifiable before the channel is submitted to
+     * {@link NotificationManager#notify(String, int, Notification)}.
      */
-    public void setSound(Uri sound) {
+    public void setSound(Uri sound, AudioAttributes audioAttributes) {
         this.mSound = sound;
+        this.mAudioAttributes = audioAttributes;
     }
 
     /**
      * Sets whether notifications posted to this channel should display notification lights,
-     * on devices that support that feature. Only modifiable before the channel is submitted to
-     * the NotificationManager.
+     * on devices that support that feature.
+     *
+     * Only modifiable before the channel is submitted to
+     * {@link NotificationManager#notify(String, int, Notification)}.
      */
     public void setLights(boolean lights) {
         this.mLights = lights;
@@ -284,16 +337,20 @@
 
     /**
      * Sets whether notification posted to this channel should vibrate. The vibration pattern can
-     * be set with {@link #setVibrationPattern(long[])}. Only modifiable before the channel is
-     * submitted to the NotificationManager.
+     * be set with {@link #setVibrationPattern(long[])}.
+     *
+     * Only modifiable before the channel is submitted to
+     * {@link NotificationManager#notify(String, int, Notification)}.
      */
     public void enableVibration(boolean vibration) {
         this.mVibrationEnabled = vibration;
     }
 
     /**
-     * Sets whether notification posted to this channel should vibrate. Only modifiable before the
-     * channel is submitted to the NotificationManager.
+     * Sets whether notification posted to this channel should vibrate.
+     *
+     * Only modifiable before the channel is submitted to
+     * {@link NotificationManager#notify(String, int, Notification)}.
      */
     public void setVibrationPattern(long[] vibrationPattern) {
         this.mVibration = vibrationPattern;
@@ -337,6 +394,13 @@
     }
 
     /**
+     * Returns the audio attributes for sound played by notifications posted to this channel.
+     */
+    public AudioAttributes getAudioAttributes() {
+        return mAudioAttributes;
+    }
+
+    /**
      * Returns whether notifications posted to this channel trigger notification lights.
      */
     public boolean shouldShowLights() {
@@ -377,6 +441,15 @@
     }
 
     /**
+     * Returns what group this channel belongs to.
+     *
+     * This is used only for visually grouping channels in the UI.
+     */
+    public String getGroup() {
+        return mGroup;
+    }
+
+    /**
      * @hide
      */
     @SystemApi
@@ -401,12 +474,13 @@
         setBypassDnd(Notification.PRIORITY_DEFAULT
                 != safeInt(parser, ATT_PRIORITY, Notification.PRIORITY_DEFAULT));
         setLockscreenVisibility(safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY));
-        setSound(safeUri(parser, ATT_SOUND));
+        setSound(safeUri(parser, ATT_SOUND), safeAudioAttributes(parser));
         setLights(safeBool(parser, ATT_LIGHTS, false));
         enableVibration(safeBool(parser, ATT_VIBRATION_ENABLED, false));
         setVibrationPattern(safeLongArray(parser, ATT_VIBRATION, null));
         setShowBadge(safeBool(parser, ATT_SHOW_BADGE, false));
         setDeleted(safeBool(parser, ATT_DELETED, false));
+        setGroup(parser.getAttributeValue(null, ATT_GROUP));
         lockFields(safeInt(parser, ATT_USER_LOCKED, 0));
     }
 
@@ -433,6 +507,12 @@
         if (getSound() != null) {
             out.attribute(null, ATT_SOUND, getSound().toString());
         }
+        if (getAudioAttributes() != null) {
+            out.attribute(null, ATT_USAGE, Integer.toString(getAudioAttributes().getUsage()));
+            out.attribute(null, ATT_CONTENT_TYPE,
+                    Integer.toString(getAudioAttributes().getContentType()));
+            out.attribute(null, ATT_FLAGS, Integer.toString(getAudioAttributes().getFlags()));
+        }
         if (shouldShowLights()) {
             out.attribute(null, ATT_LIGHTS, Boolean.toString(shouldShowLights()));
         }
@@ -451,6 +531,9 @@
         if (isDeleted()) {
             out.attribute(null, ATT_DELETED, Boolean.toString(isDeleted()));
         }
+        if (getGroup() != null) {
+            out.attribute(null, ATT_GROUP, getGroup());
+        }
 
         out.endTag(null, TAG_CHANNEL);
     }
@@ -476,15 +559,34 @@
         if (getSound() != null) {
             record.put(ATT_SOUND, getSound().toString());
         }
+        if (getAudioAttributes() != null) {
+            record.put(ATT_USAGE, Integer.toString(getAudioAttributes().getUsage()));
+            record.put(ATT_CONTENT_TYPE,
+                    Integer.toString(getAudioAttributes().getContentType()));
+            record.put(ATT_FLAGS, Integer.toString(getAudioAttributes().getFlags()));
+        }
         record.put(ATT_LIGHTS, Boolean.toString(shouldShowLights()));
         record.put(ATT_VIBRATION_ENABLED, Boolean.toString(shouldVibrate()));
         record.put(ATT_USER_LOCKED, Integer.toString(getUserLockedFields()));
         record.put(ATT_VIBRATION, longArrayToString(getVibrationPattern()));
         record.put(ATT_SHOW_BADGE, Boolean.toString(canShowBadge()));
         record.put(ATT_DELETED, Boolean.toString(isDeleted()));
+        record.put(ATT_GROUP, getGroup());
         return record;
     }
 
+    private static AudioAttributes safeAudioAttributes(XmlPullParser parser) {
+        int usage = safeInt(parser, ATT_USAGE, AudioAttributes.USAGE_NOTIFICATION);
+        int contentType = safeInt(parser, ATT_CONTENT_TYPE,
+                AudioAttributes.CONTENT_TYPE_SONIFICATION);
+        int flags = safeInt(parser, ATT_FLAGS, 0);
+        return new AudioAttributes.Builder()
+                .setUsage(usage)
+                .setContentType(contentType)
+                .setFlags(flags)
+                .build();
+    }
+
     private static Uri safeUri(XmlPullParser parser, String att) {
         final String val = parser.getAttributeValue(null, att);
         return val == null ? null : Uri.parse(val);
@@ -527,10 +629,12 @@
 
     private static String longArrayToString(long[] values) {
         StringBuffer sb = new StringBuffer();
-        for (int i = 0; i < values.length - 1; i++) {
-            sb.append(values[i]).append(DELIMITER);
+        if (values != null) {
+            for (int i = 0; i < values.length - 1; i++) {
+                sb.append(values[i]).append(DELIMITER);
+            }
+            sb.append(values[values.length - 1]);
         }
-        sb.append(values[values.length - 1]);
         return sb.toString();
     }
 
@@ -558,35 +662,46 @@
 
         NotificationChannel that = (NotificationChannel) o;
 
-        if (mImportance != that.mImportance) return false;
+        if (getImportance() != that.getImportance()) return false;
         if (mBypassDnd != that.mBypassDnd) return false;
-        if (mLockscreenVisibility != that.mLockscreenVisibility) return false;
+        if (getLockscreenVisibility() != that.getLockscreenVisibility()) return false;
         if (mLights != that.mLights) return false;
-        if (mUserLockedFields != that.mUserLockedFields) return false;
+        if (getUserLockedFields() != that.getUserLockedFields()) return false;
         if (mVibrationEnabled != that.mVibrationEnabled) return false;
         if (mShowBadge != that.mShowBadge) return false;
-        if (mDeleted != that.mDeleted) return false;
-        if (mId != null ? !mId.equals(that.mId) : that.mId != null) return false;
-        if (mName != null ? !mName.equals(that.mName) : that.mName != null) return false;
-        if (mSound != null ? !mSound.equals(that.mSound) : that.mSound != null) return false;
-        return Arrays.equals(mVibration, that.mVibration);
+        if (isDeleted() != that.isDeleted()) return false;
+        if (getId() != null ? !getId().equals(that.getId()) : that.getId() != null) return false;
+        if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null) {
+            return false;
+        }
+        if (getSound() != null ? !getSound().equals(that.getSound()) : that.getSound() != null) {
+            return false;
+        }
+        if (!Arrays.equals(mVibration, that.mVibration)) return false;
+        if (getGroup() != null ? !getGroup().equals(that.getGroup()) : that.getGroup() != null) {
+            return false;
+        }
+        return getAudioAttributes() != null ? getAudioAttributes().equals(that.getAudioAttributes())
+                : that.getAudioAttributes() == null;
 
     }
 
     @Override
     public int hashCode() {
-        int result = mId != null ? mId.hashCode() : 0;
-        result = 31 * result + (mName != null ? mName.hashCode() : 0);
-        result = 31 * result + mImportance;
+        int result = getId() != null ? getId().hashCode() : 0;
+        result = 31 * result + (getName() != null ? getName().hashCode() : 0);
+        result = 31 * result + getImportance();
         result = 31 * result + (mBypassDnd ? 1 : 0);
-        result = 31 * result + mLockscreenVisibility;
-        result = 31 * result + (mSound != null ? mSound.hashCode() : 0);
+        result = 31 * result + getLockscreenVisibility();
+        result = 31 * result + (getSound() != null ? getSound().hashCode() : 0);
         result = 31 * result + (mLights ? 1 : 0);
         result = 31 * result + Arrays.hashCode(mVibration);
-        result = 31 * result + mUserLockedFields;
+        result = 31 * result + getUserLockedFields();
         result = 31 * result + (mVibrationEnabled ? 1 : 0);
         result = 31 * result + (mShowBadge ? 1 : 0);
-        result = 31 * result + (mDeleted ? 1 : 0);
+        result = 31 * result + (isDeleted() ? 1 : 0);
+        result = 31 * result + (getGroup() != null ? getGroup().hashCode() : 0);
+        result = 31 * result + (getAudioAttributes() != null ? getAudioAttributes().hashCode() : 0);
         return result;
     }
 
@@ -605,6 +720,8 @@
                 ", mVibrationEnabled=" + mVibrationEnabled +
                 ", mShowBadge=" + mShowBadge +
                 ", mDeleted=" + mDeleted +
+                ", mGroup='" + mGroup + '\'' +
+                ", mAudioAttributes=" + mAudioAttributes +
                 '}';
     }
 }
diff --git a/core/java/android/app/NotificationChannelGroup.aidl b/core/java/android/app/NotificationChannelGroup.aidl
new file mode 100644
index 0000000..c0da037
--- /dev/null
+++ b/core/java/android/app/NotificationChannelGroup.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.app;
+
+parcelable NotificationChannelGroup;
\ No newline at end of file
diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java
new file mode 100644
index 0000000..68cac27
--- /dev/null
+++ b/core/java/android/app/NotificationChannelGroup.java
@@ -0,0 +1,187 @@
+/*
+ * 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.app;
+
+import android.annotation.SystemApi;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.service.notification.NotificationListenerService;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A grouping of related notification channels. e.g., channels that all belong to a single account.
+ */
+public final class NotificationChannelGroup implements Parcelable {
+
+    private static final String TAG_GROUP = "channelGroup";
+    private static final String ATT_NAME = "name";
+    private static final String ATT_ID = "id";
+
+    private final String mId;
+    private CharSequence mName;
+    private List<NotificationChannel> mChannels = new ArrayList<>();
+
+    /**
+     * Creates a notification channel.
+     *
+     * @param id The id of the group. Must be unique per package.
+     * @param name The user visible name of the group.
+     */
+    public NotificationChannelGroup(String id, CharSequence name) {
+        this.mId = id;
+        this.mName = name;
+    }
+
+    protected NotificationChannelGroup(Parcel in) {
+        if (in.readByte() != 0) {
+            mId = in.readString();
+        } else {
+            mId = null;
+        }
+        mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+        in.readParcelableList(mChannels, NotificationChannel.class.getClassLoader());
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (mId != null) {
+            dest.writeByte((byte) 1);
+            dest.writeString(mId);
+        } else {
+            dest.writeByte((byte) 0);
+        }
+        TextUtils.writeToParcel(mName, dest, flags);
+        dest.writeParcelableList(mChannels, flags);
+    }
+
+    /**
+     * Returns the id of this channel.
+     */
+    public String getId() {
+        return mId;
+    }
+
+    /**
+     * Returns the user visible name of this channel.
+     */
+    public CharSequence getName() {
+        return mName;
+    }
+
+    /*
+     * Returns the list of channels that belong to this group
+     *
+     * @hide
+     */
+    @SystemApi
+    public List<NotificationChannel> getChannels() {
+        return mChannels;
+    }
+
+    /**
+     * @hide
+     */
+    @SystemApi
+    public void addChannel(NotificationChannel channel) {
+        mChannels.add(channel);
+    }
+
+    /**
+     * @hide
+     */
+    @SystemApi
+    public void writeXml(XmlSerializer out) throws IOException {
+        out.startTag(null, TAG_GROUP);
+
+        out.attribute(null, ATT_ID, getId());
+        out.attribute(null, ATT_NAME, getName().toString());
+
+        out.endTag(null, TAG_GROUP);
+    }
+
+    /**
+     * @hide
+     */
+    @SystemApi
+    public JSONObject toJson() throws JSONException {
+        JSONObject record = new JSONObject();
+        record.put(ATT_ID, getId());
+        record.put(ATT_NAME, getName());
+        return record;
+    }
+
+    public static final Creator<NotificationChannelGroup> CREATOR =
+            new Creator<NotificationChannelGroup>() {
+        @Override
+        public NotificationChannelGroup createFromParcel(Parcel in) {
+            return new NotificationChannelGroup(in);
+        }
+
+        @Override
+        public NotificationChannelGroup[] newArray(int size) {
+            return new NotificationChannelGroup[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        NotificationChannelGroup that = (NotificationChannelGroup) o;
+
+        if (getId() != null ? !getId().equals(that.getId()) : that.getId() != null) return false;
+        if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null) {
+            return false;
+        }
+        return getChannels() != null ? getChannels().equals(that.getChannels())
+                : that.getChannels() == null;
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = getId() != null ? getId().hashCode() : 0;
+        result = 31 * result + (getName() != null ? getName().hashCode() : 0);
+        result = 31 * result + (getChannels() != null ? getChannels().hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "NotificationChannelGroup{" +
+                "mId='" + mId + '\'' +
+                ", mName=" + mName +
+                '}';
+    }
+}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index c0aae6d..5205959 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -383,8 +383,46 @@
     }
 
     /**
+     * Creates a group container for {@link NotificationChannel} objects.
+     *
+     * This is a no-op for groups that already exist.
+     * <p>
+     *     Group information is only used for presentation, not for behavior. Groups are optional
+     *     for channels, and you can have a mix of channels that belong to groups and channels
+     *     that do not.
+     * </p>
+     * <p>
+     *     For example, if your application supports multiple accounts, and those accounts will
+     *     have similar channels, you can create a group for each account with account specific
+     *     labels instead of appending account information to each channel's label.
+     * </p>
+     *
+     * @param group The group to create
+     */
+    public void createNotificationChannelGroup(@NonNull NotificationChannelGroup group) {
+        createNotificationChannelGroups(Arrays.asList(group));
+    }
+
+    /**
+     * Creates multiple notification channel groups.
+     *
+     * @param groups The list of groups to create
+     */
+    public void createNotificationChannelGroups(@NonNull List<NotificationChannelGroup> groups) {
+        INotificationManager service = getService();
+        try {
+            service.createNotificationChannelGroups(mContext.getPackageName(),
+                    new ParceledListSlice(groups));
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Creates a notification channel that notifications can be posted to.
      *
+     * This is a no-op for channels that already exist.
+     *
      * @param channel  the channel to create.  Note that the created channel may differ from this
      *                 value.  If the channel already exists, it will not be modified.
      */
@@ -1093,7 +1131,7 @@
      * can be used from within background operations like broadcast receivers
      * or scheduled jobs.
      *
-     * @param service Description of the service to be stopped.  The Intent must be either
+     * @param service Description of the service to be started.  The Intent must be either
      *      fully explicit (supplying a component name) or specify a specific package
      *      name it is targeted to.
      * @param id The identifier for this notification as per
diff --git a/core/java/android/app/ProfilerInfo.java b/core/java/android/app/ProfilerInfo.java
index cea7c3c..f3fe677 100644
--- a/core/java/android/app/ProfilerInfo.java
+++ b/core/java/android/app/ProfilerInfo.java
@@ -39,11 +39,16 @@
     /* Automatically stop the profiler when the app goes idle. */
     public final boolean autoStopProfiler;
 
-    public ProfilerInfo(String filename, ParcelFileDescriptor fd, int interval, boolean autoStop) {
+    /* Indicates whether to stream the profiling info to the out file continuously. */
+    public final boolean streamingOutput;
+
+    public ProfilerInfo(String filename, ParcelFileDescriptor fd, int interval, boolean autoStop,
+                        boolean streaming) {
         profileFile = filename;
         profileFd = fd;
         samplingInterval = interval;
         autoStopProfiler = autoStop;
+        streamingOutput = streaming;
     }
 
     public int describeContents() {
@@ -64,6 +69,7 @@
         }
         out.writeInt(samplingInterval);
         out.writeInt(autoStopProfiler ? 1 : 0);
+        out.writeInt(streamingOutput ? 1 : 0);
     }
 
     public static final Parcelable.Creator<ProfilerInfo> CREATOR =
@@ -82,5 +88,6 @@
         profileFd = in.readInt() != 0 ? ParcelFileDescriptor.CREATOR.createFromParcel(in) : null;
         samplingInterval = in.readInt();
         autoStopProfiler = in.readInt() != 0;
+        streamingOutput = in.readInt() != 0;
     }
 }
diff --git a/core/java/android/app/TaskStackBuilder.java b/core/java/android/app/TaskStackBuilder.java
index 0077db1..bab993f 100644
--- a/core/java/android/app/TaskStackBuilder.java
+++ b/core/java/android/app/TaskStackBuilder.java
@@ -226,7 +226,7 @@
      * Start the task stack constructed by this builder.
      *
      * @param options Additional options for how the Activity should be started.
-     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     * See {@link android.content.Context#startActivity(Intent, Bundle)}
      * Context.startActivity(Intent, Bundle)} for more details.
      */
     public void startActivities(Bundle options) {
@@ -259,7 +259,7 @@
      *              {@link Intent#fillIn(Intent, int)} to control which unspecified parts of the
      *              intent that can be supplied when the actual send happens.
      * @param options Additional options for how the Activity should be started.
-     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     * See {@link android.content.Context#startActivity(Intent, Bundle)}
      * Context.startActivity(Intent, Bundle)} for more details.
      *
      * @return The obtained PendingIntent
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 72daade..52d7386 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -34,6 +34,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ParceledListSlice;
@@ -909,6 +910,16 @@
      * or the organization name.
      *
      * <p> Use in Bundle {@link #EXTRA_PROVISIONING_DISCLAIMERS}
+     *
+     * <p> System app, i.e. application with {@link ApplicationInfo#FLAG_SYSTEM}, can also insert a
+     * disclaimer by declaring an application-level meta-data in {@code AndroidManifest.xml}.
+     * Must use it with {@link #EXTRA_PROVISIONING_DISCLAIMER_CONTENT}. Here is the example:
+     *
+     * <pre>
+     *  &lt;meta-data
+     *      android:name="android.app.extra.PROVISIONING_DISCLAIMER_HEADER"
+     *      android:resource="@string/disclaimer_header"
+     * /&gt;</pre>
      */
     public static final String EXTRA_PROVISIONING_DISCLAIMER_HEADER =
             "android.app.extra.PROVISIONING_DISCLAIMER_HEADER";
@@ -931,6 +942,16 @@
      * {@link android.content.ClipData} of the intent too.
      *
      * <p> Use in Bundle {@link #EXTRA_PROVISIONING_DISCLAIMERS}
+     *
+     * <p> System app, i.e. application with {@link ApplicationInfo#FLAG_SYSTEM}, can also insert a
+     * disclaimer by declaring an application-level meta-data in {@code AndroidManifest.xml}.
+     * Must use it with {@link #EXTRA_PROVISIONING_DISCLAIMER_HEADER}. Here is the example:
+     *
+     * <pre>
+     *  &lt;meta-data
+     *      android:name="android.app.extra.PROVISIONING_DISCLAIMER_CONTENT"
+     *      android:resource="@string/disclaimer_content"
+     * /&gt;</pre>
      */
     public static final String EXTRA_PROVISIONING_DISCLAIMER_CONTENT =
             "android.app.extra.PROVISIONING_DISCLAIMER_CONTENT";
@@ -1091,6 +1112,30 @@
     public static final String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION";
 
     /**
+     * Constant to indicate the feature of disabling the camera. Used as argument to
+     * {@link #createAdminSupportIntent(String)}.
+     * @see #setCameraDisabled(ComponentName, boolean)
+     */
+    public static final String POLICY_DISABLE_CAMERA = "policy_disable_camera";
+
+    /**
+     * Constant to indicate the feature of disabling screen captures. Used as argument to
+     * {@link #createAdminSupportIntent(String)}.
+     * @see #setScreenCaptureDisabled(ComponentName, boolean)
+     */
+    public static final String POLICY_DISABLE_SCREEN_CAPTURE = "policy_disable_screen_capture";
+
+    /**
+     * A String indicating a specific restricted feature. Can be a user restriction from the
+     * {@link UserManager}, e.g. {@link UserManager#DISALLOW_ADJUST_VOLUME}, or one of the values
+     * {@link #POLICY_DISABLE_CAMERA} or {@link #POLICY_DISABLE_SCREEN_CAPTURE}.
+     * @see #createAdminSupportIntent(String)
+     * @hide
+     */
+    @TestApi
+    public static final String EXTRA_RESTRICTION = "android.app.extra.RESTRICTION";
+
+    /**
      * Activity action: have the user enter a new password. This activity should
      * be launched after using {@link #setPasswordQuality(ComponentName, int)},
      * or {@link #setPasswordMinimumLength(ComponentName, int)} to have the user
@@ -1132,9 +1177,9 @@
             = "android.app.action.SHOW_DEVICE_MONITORING_DIALOG";
 
     /**
-     * Broadcast Action: Sent after application delegation scopes are changed. The new list of
-     * delegation scopes will be sent in an extra identified by the {@link #EXTRA_DELEGATION_SCOPES}
-     * key.
+     * Broadcast Action: Sent after application delegation scopes are changed. The new delegation
+     * scopes will be sent in an {@code ArrayList<String>} extra identified by the
+     * {@link #EXTRA_DELEGATION_SCOPES} key.
      *
      * <p class=”note”> Note: This is a protected intent that can only be sent by the system.</p>
      */
@@ -1143,7 +1188,7 @@
             "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED";
 
     /**
-     * A list of Strings corresponding to the delegation scopes given to an app in the
+     * An {@code ArrayList<String>} corresponding to the delegation scopes given to an app in the
      * {@link #ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED} broadcast.
      */
     public static final String EXTRA_DELEGATION_SCOPES = "android.app.extra.DELEGATION_SCOPES";
@@ -3624,6 +3669,11 @@
      * Granted APIs are determined by {@code scopes}, which is a list of the {@code DELEGATION_*}
      * constants.
      * <p>
+     * A broadcast with the {@link #ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED} action will be
+     * sent to the {@code delegatePackage} with its new scopes in an {@code ArrayList<String>} extra
+     * under the {@link #EXTRA_DELEGATION_SCOPES} key. The broadcast is sent with the
+     * {@link Intent#FLAG_RECEIVER_REGISTERED_ONLY} flag.
+     * <p>
      * Delegated scopes are a per-user state. The delegated access is persistent until it is later
      * cleared by calling this method with an empty {@code scopes} list or uninstalling the
      * {@code delegatePackage}.
@@ -3659,7 +3709,7 @@
      * @throws SecurityException if {@code admin} is not a device or a profile owner.
      */
      @NonNull
-     public List<String> getDelegatedScopes(@NonNull ComponentName admin,
+     public List<String> getDelegatedScopes(@Nullable ComponentName admin,
              @NonNull String delegatedPackage) {
          throwIfParentInstance("getDelegatedScopes");
          if (mService != null) {
@@ -5827,6 +5877,33 @@
     }
 
     /**
+     * Called by any app to display a support dialog when a feature was disabled by an admin.
+     * This returns an intent that can be used with {@link Context#startActivity(Intent)} to
+     * display the dialog. It will tell the user that the feature indicated by {@code restriction}
+     * was disabled by an admin, and include a link for more information. The default content of
+     * the dialog can be changed by the restricting admin via
+     * {@link #setShortSupportMessage(ComponentName, CharSequence)}. If the restriction is not
+     * set (i.e. the feature is available), then the return value will be {@code null}.
+     * @param restriction Indicates for which feature the dialog should be displayed. Can be a
+     *            user restriction from {@link UserManager}, e.g.
+     *            {@link UserManager#DISALLOW_ADJUST_VOLUME}, or one of the constants
+     *            {@link #POLICY_DISABLE_CAMERA} or {@link #POLICY_DISABLE_SCREEN_CAPTURE}.
+     * @return Intent An intent to be used to start the dialog-activity if the restriction is
+     *            set by an admin, or null if the restriction does not exist or no admin set it.
+     */
+    public Intent createAdminSupportIntent(@NonNull String restriction) {
+        throwIfParentInstance("createAdminSupportIntent");
+        if (mService != null) {
+            try {
+                return mService.createAdminSupportIntent(restriction);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        return null;
+    }
+
+    /**
      * Hide or unhide packages. When a package is hidden it is unavailable for use, but the data and
      * actual package file remain. This function can be called by a device owner, profile owner, or
      * by a delegate given the {@link #DELEGATION_PACKAGE_ACCESS} scope via
@@ -7536,8 +7613,8 @@
     }
 
     /**
-     * Called by a device owner to bind to a service from a profile owner of a managed profile or
-     * vice versa. See {@link #getBindDeviceAdminTargetUsers} for a definition of which
+     * Called by a device owner to bind to a service from a profile owner or vice versa.
+     * See {@link #getBindDeviceAdminTargetUsers} for a definition of which
      * device/profile owners are allowed to bind to services of another profile/device owner.
      * <p>
      * The service must be unexported. Note that the {@link Context} used to obtain this
@@ -7583,14 +7660,10 @@
      * Returns the list of target users that the calling device or profile owner can use when
      * calling {@link #bindDeviceAdminServiceAsUser}.
      * <p>
-     * A device owner can bind to a service from a profile owner of a managed profile and
-     * vice versa, provided that:
+     * A device owner can bind to a service from a profile owner and vice versa, provided that:
      * <ul>
      * <li>Both belong to the same package name.
-     * <li>The managed profile is a profile of the user where the device owner is set.
-     *     See {@link UserManager#getUserProfiles()}
-     * <li>Both users are affiliated.
-     *     See {@link #setAffiliationIds}.
+     * <li>Both users are affiliated. See {@link #setAffiliationIds}.
      * </ul>
      */
     public @NonNull List<UserHandle> getBindDeviceAdminTargetUsers(@NonNull ComponentName admin) {
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 7604af8..79fe10e 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -201,6 +201,7 @@
     List getPermittedInputMethodsForCurrentUser();
     boolean isInputMethodPermittedByAdmin(in ComponentName admin, String packageName, int userId);
 
+    Intent createAdminSupportIntent(in String restriction);
     boolean setApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName, boolean hidden);
     boolean isApplicationHidden(in ComponentName admin, in String callerPackage, in String packageName);
 
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index bad6325..45d9fb7 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -493,7 +493,7 @@
      * <p class="note">Attempting to back up files in directories that are ignored by
      * the backup system will have no effect.  For example, if the app calls this method
      * with a file inside the {@link #getNoBackupFilesDir()} directory, it will be ignored.
-     * See {@link #onFullBackup(FullBackupDataOutput) for details on what directories
+     * See {@link #onFullBackup(FullBackupDataOutput)} for details on what directories
      * are excluded from backups.
      *
      * @param file The file to be backed up.  The file must exist and be readable by
diff --git a/core/java/android/app/usage/StorageStatsManager.java b/core/java/android/app/usage/StorageStatsManager.java
index 695994b..9d30771 100644
--- a/core/java/android/app/usage/StorageStatsManager.java
+++ b/core/java/android/app/usage/StorageStatsManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.WorkerThread;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.os.RemoteException;
 import android.os.UserHandle;
 
@@ -99,6 +100,8 @@
      * @param volumeUuid the UUID of the storage volume you're interested in, or
      *            {@code null} to specify the default internal storage.
      * @param uid the UID you're interested in.
+     * @see ApplicationInfo#volumeUuid
+     * @see ApplicationInfo#uid
      */
     @WorkerThread
     public StorageStats queryStatsForUid(String volumeUuid, int uid) {
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 9980e966..077331e 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -1072,6 +1072,18 @@
     }
 
     /**
+     * Return {@code TRUE} if the default launcher supports
+     * {@link #requestPinAppWidget(ComponentName, PendingIntent)}
+     */
+    public boolean isRequestPinAppWidgetSupported() {
+        try {
+            return mService.isRequestPinAppWidgetSupported();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Request to pin an app widget on the current launcher. It's up to the launcher to accept this
      * request (optionally showing a user confirmation). If the request is accepted, the caller will
      * get a confirmation with extra {@link #EXTRA_APPWIDGET_ID}.
@@ -1095,6 +1107,7 @@
      *
      * @see android.content.pm.ShortcutManager#isRequestPinShortcutSupported()
      * @see android.content.pm.ShortcutManager#requestPinShortcut(ShortcutInfo, IntentSender)
+     * @see #isRequestPinAppWidgetSupported()
      *
      * @throws IllegalStateException The caller doesn't have a foreground activity or a foreground
      * service or when the user is locked.
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 885b42f3..4534767 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1184,6 +1184,25 @@
     }
 
     /**
+     * Get the end time of the latest remote device discovery process.
+     * @return the latest time that the bluetooth adapter was/will be in discovery mode,
+     * in milliseconds since the epoch.
+     * This time can be in the future if {@link #startDiscovery()} has been called recently.
+     * @hide
+     */
+    public long getDiscoveryEndMillis() {
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null) return mService.getDiscoveryEndMillis();
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+        return -1;
+    }
+
+    /**
      * Start the remote device discovery process.
      * <p>The discovery process usually involves an inquiry scan of about 12
      * seconds, followed by a page scan of each new device to retrieve its
diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java
index 52cd2de..a37a0b3 100644
--- a/core/java/android/bluetooth/BluetoothCodecConfig.java
+++ b/core/java/android/bluetooth/BluetoothCodecConfig.java
@@ -51,9 +51,10 @@
     // NOTE: The values should be same as those listed in the following file:
     //   hardware/libhardware/include/hardware/bt_av.h
     public static final int SOURCE_CODEC_TYPE_SBC     = 0;
-    public static final int SOURCE_CODEC_TYPE_APTX    = 1;
-    public static final int SOURCE_CODEC_TYPE_APTX_HD = 2;
-    public static final int SOURCE_CODEC_TYPE_LDAC    = 3;
+    public static final int SOURCE_CODEC_TYPE_AAC     = 1;
+    public static final int SOURCE_CODEC_TYPE_APTX    = 2;
+    public static final int SOURCE_CODEC_TYPE_APTX_HD = 3;
+    public static final int SOURCE_CODEC_TYPE_LDAC    = 4;
 
     public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
 
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 7c5458b..53fef2a 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -52,6 +52,7 @@
     boolean startDiscovery();
     boolean cancelDiscovery();
     boolean isDiscovering();
+    long getDiscoveryEndMillis();
 
     int getAdapterConnectionState();
     int getProfileConnectionState(int profile);
diff --git a/core/java/android/content/ContentValues.java b/core/java/android/content/ContentValues.java
index 7ed827c..3a87cb3 100644
--- a/core/java/android/content/ContentValues.java
+++ b/core/java/android/content/ContentValues.java
@@ -414,7 +414,11 @@
             return (Boolean) value;
         } catch (ClassCastException e) {
             if (value instanceof CharSequence) {
-                return Boolean.valueOf(value.toString());
+                // Note that we also check against 1 here because SQLite's internal representation
+                // for booleans is an integer with a value of 0 or 1. Without this check, boolean
+                // values obtained via DatabaseUtils#cursorRowToContentValues will always return
+                // false.
+                return Boolean.valueOf(value.toString()) || "1".equals(value);
             } else if (value instanceof Number) {
                 return ((Number) value).intValue() != 0;
             } else {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index f00f605..f610a29 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1672,7 +1672,7 @@
      *
      * @param intents An array of Intents to be started.
      * @param options Additional options for how the Activity should be started.
-     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     * See {@link android.content.Context#startActivity(Intent, Bundle)}
      * Context.startActivity(Intent, Bundle)} for more details.
      *
      * @throws ActivityNotFoundException &nbsp;
@@ -1700,7 +1700,7 @@
      * @param intents An array of Intents to be started.
      * @param options Additional options for how the Activity should be started.
      * @param userHandle The user for whom to launch the activities
-     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     * See {@link android.content.Context#startActivity(Intent, Bundle)}
      * Context.startActivity(Intent, Bundle)} for more details.
      *
      * @throws ActivityNotFoundException &nbsp;
@@ -1749,7 +1749,7 @@
      * <var>flagsMask</var>
      * @param extraFlags Always set to 0.
      * @param options Additional options for how the Activity should be started.
-     * See {@link android.content.Context#startActivity(Intent, Bundle)
+     * See {@link android.content.Context#startActivity(Intent, Bundle)}
      * Context.startActivity(Intent, Bundle)} for more details.  If options
      * have also been supplied by the IntentSender, options given here will
      * override any that conflict with those given by the IntentSender.
@@ -3754,6 +3754,16 @@
     public static final String INCIDENT_SERVICE = "incident";
 
     /**
+     * Use with {@link #getSystemService} to retrieve a {@link
+     * android.content.om.OverlayManager} for managing overlay packages.
+     *
+     * @see #getSystemService
+     * @see android.content.om.OverlayManager
+     * @hide
+     */
+    public static final String OVERLAY_SERVICE = "overlay";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 44e106e..111b4d6 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3133,6 +3133,40 @@
             "android.intent.action.MEDIA_RESOURCE_GRANTED";
 
     /**
+     * Broadcast Action: An overlay package has been installed. The data
+     * contains the name of the added overlay package.
+     * @hide
+     */
+    public static final String ACTION_OVERLAY_ADDED = "android.intent.action.OVERLAY_ADDED";
+
+    /**
+     * Broadcast Action: An overlay package has changed. The data contains the
+     * name of the overlay package which has changed. This is broadcast on all
+     * changes to the OverlayInfo returned by {@link
+     * android.content.om.IOverlayManager#getOverlayInfo(String, int)}. The
+     * most common change is a state change that will change whether the
+     * overlay is enabled or not.
+     * @hide
+     */
+    public static final String ACTION_OVERLAY_CHANGED = "android.intent.action.OVERLAY_CHANGED";
+
+    /**
+     * Broadcast Action: An overlay package has been removed. The data contains
+     * the name of the overlay package which has been removed.
+     * @hide
+     */
+    public static final String ACTION_OVERLAY_REMOVED = "android.intent.action.OVERLAY_REMOVED";
+
+    /**
+     * Broadcast Action: The order of a package's list of overlay packages has
+     * changed. The data contains the package name of the overlay package that
+     * had its position in the list adjusted.
+     * @hide
+     */
+    public static final String
+            ACTION_OVERLAY_PRIORITY_CHANGED = "android.intent.action.OVERLAY_PRIORITY_CHANGED";
+
+    /**
      * Activity Action: Allow the user to select and return one or more existing
      * documents. When invoked, the system will display the various
      * {@link DocumentsProvider} instances installed on the device, letting the
@@ -8357,7 +8391,7 @@
      * @return Returns a bit mask of {@link #FILL_IN_ACTION},
      * {@link #FILL_IN_DATA}, {@link #FILL_IN_CATEGORIES}, {@link #FILL_IN_PACKAGE},
      * {@link #FILL_IN_COMPONENT}, {@link #FILL_IN_SOURCE_BOUNDS},
-     * {@link #FILL_IN_SELECTOR} and {@link #FILL_IN_CLIP_DATA indicating which fields were
+     * {@link #FILL_IN_SELECTOR} and {@link #FILL_IN_CLIP_DATA} indicating which fields were
      * changed.
      */
     @FillInFlags
diff --git a/core/java/android/content/SyncRequest.java b/core/java/android/content/SyncRequest.java
index 541ebbd..dd53eac 100644
--- a/core/java/android/content/SyncRequest.java
+++ b/core/java/android/content/SyncRequest.java
@@ -175,7 +175,7 @@
     }
 
     /**
-     * Builder class for a @link SyncRequest. As you build your SyncRequest this class will also
+     * Builder class for a {@link SyncRequest}. As you build your SyncRequest this class will also
      * perform validation.
      */
     public static class Builder {
diff --git a/core/java/android/content/om/IOverlayManager.aidl b/core/java/android/content/om/IOverlayManager.aidl
new file mode 100644
index 0000000..4f5d960
--- /dev/null
+++ b/core/java/android/content/om/IOverlayManager.aidl
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.om;
+
+import android.content.om.OverlayInfo;
+
+/**
+ * Api for getting information about overlay packages.
+ *
+ * {@hide}
+ */
+interface IOverlayManager {
+    /**
+     * Returns information about all installed overlay packages for the
+     * specified user. If there are no installed overlay packages for this user,
+     * an empty map is returned (i.e. null is never returned). The returned map is a
+     * mapping of target package names to lists of overlays. Each list for a
+     * given target package is sorted in priority order, with the overlay with
+     * the highest priority at the end of the list.
+     *
+     * @param userId The user to get the OverlayInfos for.
+     * @return A Map<String, List<OverlayInfo>> with target package names
+     *         mapped to lists of overlays; if no overlays exist for the
+     *         requested user, an empty map is returned.
+     */
+    Map getAllOverlays(in int userId);
+
+    /**
+     * Returns information about all overlays for the given target package for
+     * the specified user. The returned list is ordered according to the
+     * overlay priority with the highest priority at the end of the list.
+     *
+     * @param targetPackageName The name of the target package.
+     * @param userId The user to get the OverlayInfos for.
+     * @return A list of OverlayInfo objects; if no overlays exist for the
+     *         requested package, an empty list is returned.
+     */
+    List getOverlayInfosForTarget(in String targetPackageName, in int userId);
+
+    /**
+     * Returns information about the overlay with the given package name for the
+     * specified user.
+     *
+     * @param packageName The name of the overlay package.
+     * @param userId The user to get the OverlayInfo for.
+     * @return The OverlayInfo for the overlay package; or null if no such
+     *         overlay package exists.
+     */
+    OverlayInfo getOverlayInfo(in String packageName, in int userId);
+
+    /**
+     * Request that an overlay package be enabled or disabled when possible to
+     * do so.
+     *
+     * It is always possible to disable an overlay, but due to technical and
+     * security reasons it may not always be possible to enable an overlay. An
+     * example of the latter is when the related target package is not
+     * installed. If the technical obstacle is later overcome, the overlay is
+     * automatically enabled at that point in time.
+     *
+     * An enabled overlay is a part of target package's resources, i.e. it will
+     * be part of any lookups performed via {@link android.content.res.Resources}
+     * and {@link android.content.res.AssetManager}. A disabled overlay will no
+     * longer affect the resources of the target package. If the target is
+     * currently running, its outdated resources will be replaced by new ones.
+     * This happens the same way as when an application enters or exits split
+     * window mode.
+     *
+     * @param packageName The name of the overlay package.
+     * @param enable true to enable the overlay, false to disable it.
+     * @param userId The user for which to change the overlay.
+     * @return true if the system successfully registered the request, false
+     *         otherwise.
+     */
+    boolean setEnabled(in String packageName, in boolean enable, in int userId);
+
+    /**
+     * Change the priority of the given overlay to be just higher than the
+     * overlay with package name newParentPackageName. Both overlay packages
+     * must have the same target and user.
+     *
+     * @see getOverlayInfosForTarget
+     *
+     * @param packageName The name of the overlay package whose priority should
+     *        be adjusted.
+     * @param newParentPackageName The name of the overlay package the newly
+     *        adjusted overlay package should just outrank.
+     * @param userId The user for which to change the overlay.
+     */
+    boolean setPriority(in String packageName, in String newParentPackageName, in int userId);
+
+    /**
+     * Change the priority of the given overlay to the highest priority relative to
+     * the other overlays with the same target and user.
+     *
+     * @see getOverlayInfosForTarget
+     *
+     * @param packageName The name of the overlay package whose priority should
+     *        be adjusted.
+     * @param userId The user for which to change the overlay.
+     */
+    boolean setHighestPriority(in String packageName, in int userId);
+
+    /**
+     * Change the priority of the overlay to the lowest priority relative to
+     * the other overlays for the same target and user.
+     *
+     * @see getOverlayInfosForTarget
+     *
+     * @param packageName The name of the overlay package whose priority should
+     *        be adjusted.
+     * @param userId The user for which to change the overlay.
+     */
+    boolean setLowestPriority(in String packageName, in int userId);
+}
diff --git a/core/java/android/content/om/OverlayInfo.aidl b/core/java/android/content/om/OverlayInfo.aidl
new file mode 100644
index 0000000..e7d413d
--- /dev/null
+++ b/core/java/android/content/om/OverlayInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.om;
+
+parcelable OverlayInfo;
diff --git a/core/java/android/content/om/OverlayInfo.java b/core/java/android/content/om/OverlayInfo.java
new file mode 100644
index 0000000..1a207ba
--- /dev/null
+++ b/core/java/android/content/om/OverlayInfo.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.om;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Immutable overlay information about a package. All PackageInfos that
+ * represent an overlay package will have a corresponding OverlayInfo.
+ *
+ * @hide
+ */
+public final class OverlayInfo implements Parcelable {
+    /**
+     * An internal state used as the initial state of an overlay. OverlayInfo
+     * objects exposed outside the {@link
+     * com.android.server.om.OverlayManagerService} should never have this
+     * state.
+     */
+    public static final int STATE_UNKNOWN = -1;
+
+    /**
+     * The target package of the overlay is not installed. The overlay cannot be enabled.
+     */
+    public static final int STATE_MISSING_TARGET = 0;
+
+    /**
+     * Creation of idmap file failed (e.g. no matching resources). The overlay
+     * cannot be enabled.
+     */
+    public static final int STATE_NO_IDMAP = 1;
+
+    /**
+     * The overlay is currently disabled. It can be enabled.
+     *
+     * @see IOverlayManager.setEnabled
+     */
+    public static final int STATE_DISABLED = 2;
+
+    /**
+     * The overlay is currently enabled. It can be disabled.
+     *
+     * @see IOverlayManager.setEnabled
+     */
+    public static final int STATE_ENABLED = 3;
+
+    /**
+     * Package name of the overlay package
+     */
+    public final String packageName;
+
+    /**
+     * Package name of the target package
+     */
+    public final String targetPackageName;
+
+    /**
+     * Full path to the base APK for this overlay package
+     */
+    public final String baseCodePath;
+
+    /**
+     * The state of this OverlayInfo as defined by the STATE_* constants in this class.
+     *
+     * @see #STATE_MISSING_TARGET
+     * @see #STATE_NO_IDMAP
+     * @see #STATE_DISABLED
+     * @see #STATE_ENABLED
+     */
+    public final int state;
+
+    /**
+     * User handle for which this overlay applies
+     */
+    public final int userId;
+
+    /**
+     * Create a new OverlayInfo based on source with an updated state.
+     *
+     * @param source the source OverlayInfo to base the new instance on
+     * @param state the new state for the source OverlayInfo
+     */
+    public OverlayInfo(@NonNull OverlayInfo source, int state) {
+        this(source.packageName, source.targetPackageName, source.baseCodePath, state,
+                source.userId);
+    }
+
+    public OverlayInfo(@NonNull String packageName, @NonNull String targetPackageName,
+            @NonNull String baseCodePath, int state, int userId) {
+        this.packageName = packageName;
+        this.targetPackageName = targetPackageName;
+        this.baseCodePath = baseCodePath;
+        this.state = state;
+        this.userId = userId;
+        ensureValidState();
+    }
+
+    public OverlayInfo(Parcel source) {
+        packageName = source.readString();
+        targetPackageName = source.readString();
+        baseCodePath = source.readString();
+        state = source.readInt();
+        userId = source.readInt();
+        ensureValidState();
+    }
+
+    private void ensureValidState() {
+        if (packageName == null) {
+            throw new IllegalArgumentException("packageName must not be null");
+        }
+        if (targetPackageName == null) {
+            throw new IllegalArgumentException("targetPackageName must not be null");
+        }
+        if (baseCodePath == null) {
+            throw new IllegalArgumentException("baseCodePath must not be null");
+        }
+        switch (state) {
+            case STATE_UNKNOWN:
+            case STATE_MISSING_TARGET:
+            case STATE_NO_IDMAP:
+            case STATE_DISABLED:
+            case STATE_ENABLED:
+                break;
+            default:
+                throw new IllegalArgumentException("State " + state + " is not a valid state");
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(packageName);
+        dest.writeString(targetPackageName);
+        dest.writeString(baseCodePath);
+        dest.writeInt(state);
+        dest.writeInt(userId);
+    }
+
+    public static final Parcelable.Creator<OverlayInfo> CREATOR = new Parcelable.Creator<OverlayInfo>() {
+        @Override
+        public OverlayInfo createFromParcel(Parcel source) {
+            return new OverlayInfo(source);
+        }
+
+        @Override
+        public OverlayInfo[] newArray(int size) {
+            return new OverlayInfo[size];
+        }
+    };
+
+    /**
+     * Return true if this overlay is enabled, i.e. should be used to overlay
+     * the resources in the target package.
+     *
+     * Disabled overlay packages are installed but are currently not in use.
+     *
+     * @return true if the overlay is enabled, else false.
+     */
+    public boolean isEnabled() {
+        switch (state) {
+            case STATE_ENABLED:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    /**
+     * Translate a state to a human readable string. Only intended for
+     * debugging purposes.
+     *
+     * @see #STATE_MISSING_TARGET
+     * @see #STATE_NO_IDMAP
+     * @see #STATE_DISABLED
+     * @see #STATE_ENABLED
+     *
+     * @return a human readable String representing the state.
+     */
+    public static String stateToString(int state) {
+        switch (state) {
+            case STATE_UNKNOWN:
+                return "STATE_UNKNOWN";
+            case STATE_MISSING_TARGET:
+                return "STATE_MISSING_TARGET";
+            case STATE_NO_IDMAP:
+                return "STATE_NO_IDMAP";
+            case STATE_DISABLED:
+                return "STATE_DISABLED";
+            case STATE_ENABLED:
+                return "STATE_ENABLED";
+            default:
+                return "<unknown state>";
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + userId;
+        result = prime * result + state;
+        result = prime * result + ((packageName == null) ? 0 : packageName.hashCode());
+        result = prime * result + ((targetPackageName == null) ? 0 : targetPackageName.hashCode());
+        result = prime * result + ((baseCodePath == null) ? 0 : baseCodePath.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        OverlayInfo other = (OverlayInfo) obj;
+        if (userId != other.userId) {
+            return false;
+        }
+        if (state != other.state) {
+            return false;
+        }
+        if (!packageName.equals(other.packageName)) {
+            return false;
+        }
+        if (!targetPackageName.equals(other.targetPackageName)) {
+            return false;
+        }
+        if (!baseCodePath.equals(other.baseCodePath)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "OverlayInfo { overlay=" + packageName + ", target=" + targetPackageName + ", state="
+                + state + " (" + stateToString(state) + "), userId=" + userId + " }";
+    }
+}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 3d9ba96..ec74617 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -596,8 +596,13 @@
      */
     public int largestWidthLimitDp = 0;
 
-    /** {@hide} */
+    /**
+     * UUID of the storage volume on which this application is being hosted. For
+     * apps hosted on the default internal storage at
+     * {@link Environment#getDataDirectory()}, the UUID value is {@code null}.
+     */
     public String volumeUuid;
+
     /** {@hide} */
     public String scanSourceDir;
     /** {@hide} */
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 7750430..f0a9ec3 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -605,4 +605,6 @@
     int getInstallReason(String packageName, int userId);
 
     ParceledListSlice getSharedLibraries(int flags, int userId);
+
+    boolean canRequestPackageInstalls(String packageName, int userId);
 }
diff --git a/core/java/android/content/pm/IShortcutService.aidl b/core/java/android/content/pm/IShortcutService.aidl
index c90134a..03124be 100644
--- a/core/java/android/content/pm/IShortcutService.aidl
+++ b/core/java/android/content/pm/IShortcutService.aidl
@@ -71,5 +71,5 @@
 
     void applyRestore(in byte[] payload, int user);
 
-    boolean isRequestPinShortcutSupported(int user);
+    boolean isRequestPinItemSupported(int user, int requestType);
 }
\ No newline at end of file
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 57d2ba7..999b34f 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -93,22 +93,40 @@
      * @see #EXTRA_PIN_ITEM_REQUEST
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_CONFIRM_PIN_ITEM =
-            "android.content.pm.action.CONFIRM_PIN_ITEM";
+    public static final String ACTION_CONFIRM_PIN_SHORTCUT =
+            "android.content.pm.action.CONFIRM_PIN_SHORTCUT";
 
     /**
-     * An extra for {@link #ACTION_CONFIRM_PIN_ITEM} containing a
-     * {@link ShortcutInfo} of the shortcut the publisher app asked to pin.
+     * Activity Action: For the default launcher to show the confirmation dialog to create
+     * a pinned app widget.
+     *
+     * <p>See the {@link android.appwidget.AppWidgetManager#requestPinAppWidget} javadoc for
+     * details.
+     *
+     * <p>
+     * Use {@link #getPinItemRequest(Intent)} to get a {@link PinItemRequest} object,
+     * and call {@link PinItemRequest#accept(Bundle)}
+     * if the user accepts.  If the user doesn't accept, no further action is required.
+     *
+     * @see #EXTRA_PIN_ITEM_REQUEST
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_CONFIRM_PIN_APPWIDGET =
+            "android.content.pm.action.CONFIRM_PIN_APPWIDGET";
+
+    /**
+     * An extra for {@link #ACTION_CONFIRM_PIN_SHORTCUT} &amp; {@link #ACTION_CONFIRM_PIN_APPWIDGET}
+     * containing a {@link PinItemRequest} of appropriate type asked to pin.
      *
      * <p>A helper function {@link #getPinItemRequest(Intent)} can be used
      * instead of using this constant directly.
      *
-     * @see #ACTION_CONFIRM_PIN_ITEM
+     * @see #ACTION_CONFIRM_PIN_SHORTCUT
+     * @see #ACTION_CONFIRM_PIN_APPWIDGET
      */
     public static final String EXTRA_PIN_ITEM_REQUEST =
             "android.content.pm.extra.PIN_ITEM_REQUEST";
 
-
     private Context mContext;
     private ILauncherApps mService;
     private PackageManager mPm;
@@ -1208,8 +1226,9 @@
     }
 
     /**
-     * Represents a "pin shortcut" request made by an app, which is sent with
-     * an {@link #ACTION_CONFIRM_PIN_ITEM} intent to the default launcher app.
+     * Represents a "pin shortcut" or a "pin appwidget" request made by an app, which is sent with
+     * an {@link #ACTION_CONFIRM_PIN_SHORTCUT} or {@link #ACTION_CONFIRM_PIN_APPWIDGET} intent
+     * respectively to the default launcher app.
      *
      * <p>Note the launcher may receive a request to pin a shortcut that is already pinned, because
      * the user may actually want to have multiple icons of the same shortcut on the launcher.
@@ -1218,6 +1237,9 @@
      * even if the launcher does not call it, the shortcut is already pinned.  Also in this case,
      * the {@code options} argument to {@link #accept(Bundle)} will be ignored.
      *
+     * <p>For AppWidget pin requests launcher should send back the appwidget id as an extra for
+     * {@link #accept(Bundle)} as {@link android.appwidget.AppWidgetManager#EXTRA_APPWIDGET_ID}.
+     *
      * @see #EXTRA_PIN_ITEM_REQUEST
      * @see #getPinItemRequest(Intent)
      */
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index ffcb1f3..76c69ca 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2969,6 +2969,14 @@
             @PermissionInfoFlags int flags) throws NameNotFoundException;
 
     /**
+     * Returns true if Permission Review Mode is enabled, false otherwise.
+     *
+     * @hide
+     */
+    @TestApi
+    public abstract boolean isPermissionReviewModeEnabled();
+
+    /**
      * Retrieve all of the information we know about a particular group of
      * permissions.
      *
@@ -6059,4 +6067,21 @@
     @TestApi
     public abstract @InstallReason int getInstallReason(String packageName,
             @NonNull UserHandle user);
+
+    /**
+     * Checks whether the calling package is allowed to request package installs through package
+     * installer. Apps are encouraged to call this api before launching the package installer via
+     * intent {@link android.content.Intent#ACTION_INSTALL_PACKAGE}. Starting from Android O, the
+     * user can explicitly choose what external sources they trust to install apps on the device.
+     * If this api returns false, the install request will be blocked by the package installer and
+     * a dialog will be shown to the user with an option to launch settings to change their
+     * preference. An application must target Android O or higher and declare permission
+     * {@link android.Manifest.permission#REQUEST_INSTALL_PACKAGES} in order to use this api.
+     *
+     * @return true if the calling package is trusted by the user to request install packages on
+     * the device, false otherwise.
+     * @see {@link android.content.Intent#ACTION_INSTALL_PACKAGE}
+     * @see {@link android.provider.Settings#ACTION_MANAGE_EXTERNAL_SOURCES}
+     */
+    public abstract boolean canRequestPackageInstalls();
 }
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index a1747c7..e3e02b1f 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -246,4 +246,54 @@
      * @return The SetupWizard package name.
      */
     public abstract String getSetupWizardPackageName();
+
+    public interface ExternalSourcesPolicy {
+
+        int USER_TRUSTED = 0;   // User has trusted the package to install apps
+        int USER_BLOCKED = 1;   // User has blocked the package to install apps
+        int USER_DEFAULT = 2;   // Default code to use when user response is unavailable
+
+        /**
+         * Checks the user preference for whether a package is trusted to request installs through
+         * package installer
+         *
+         * @param packageName The package to check for
+         * @param uid the uid in which the package is running
+         * @return {@link USER_TRUSTED} if the user has trusted the package, {@link USER_BLOCKED}
+         * if user has blocked requests from the package, {@link USER_DEFAULT} if the user response
+         * is not yet available
+         */
+        int getPackageTrustedToInstallApps(String packageName, int uid);
+    }
+
+    public abstract void setExternalSourcesPolicy(ExternalSourcesPolicy policy);
+
+    /**
+     * Get all overlay packages for a user.
+     * @param userId The user for which to get the overlays.
+     * @return A list of overlay packages. An empty list is returned if the
+     *         user has no installed overlay packages.
+     */
+    public abstract List<PackageInfo> getOverlayPackages(int userId);
+
+    /**
+     * Get the names of all target packages for a user.
+     * @param userId The user for which to get the package names.
+     * @return A list of target package names. This list includes the "android" package.
+     */
+    public abstract List<String> getTargetPackageNames(int userId);
+
+    /**
+     * Set which overlay to use for a package.
+     * @param userId The user for which to update the overlays.
+     * @param targetPackageName The package name of the package for which to update the overlays.
+     * @param overlayPackageNames The complete list of overlay packages that should be enabled for
+     *                            the target. Previously enabled overlays not specified in the list
+     *                            will be disabled. Pass in null or an empty list to disable
+     *                            all overlays. The order of the items is significant if several
+     *                            overlays modify the same resource.
+     * @return true if all packages names were known by the package manager, false otherwise
+     */
+    public abstract boolean setEnabledOverlayPackages(int userId, String targetPackageName,
+            List<String> overlayPackageNames);
 }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 8223726..7032cc0 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1232,7 +1232,7 @@
         XmlResourceParser parser = null;
         try {
             res = new Resources(assets, mMetrics, null);
-            assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                     Build.VERSION.RESOURCES_SDK_INT);
             parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
 
@@ -1568,7 +1568,7 @@
 
     private static AssetManager newConfiguredAssetManager() {
         AssetManager assetManager = new AssetManager();
-        assetManager.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        assetManager.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                 Build.VERSION.RESOURCES_SDK_INT);
         return assetManager;
     }
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index 805054f..fb280a1 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -830,7 +830,8 @@
      */
     public boolean isRequestPinShortcutSupported() {
         try {
-            return mService.isRequestPinShortcutSupported(injectMyUserId());
+            return mService.isRequestPinItemSupported(injectMyUserId(),
+                    LauncherApps.PinItemRequest.REQUEST_TYPE_SHORTCUT);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
index 4773c73..87a6d4a 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -74,4 +74,6 @@
     public abstract boolean requestPinAppWidget(@NonNull String callingPackage,
             @NonNull AppWidgetProviderInfo appWidget, @Nullable IntentSender resultIntent,
             int userId);
+
+    public abstract boolean isRequestPinItemSupported(int callingUserId, int requestType);
 }
diff --git a/core/java/android/content/pm/split/DefaultSplitAssetLoader.java b/core/java/android/content/pm/split/DefaultSplitAssetLoader.java
index 5a9966d..99eb470 100644
--- a/core/java/android/content/pm/split/DefaultSplitAssetLoader.java
+++ b/core/java/android/content/pm/split/DefaultSplitAssetLoader.java
@@ -65,7 +65,7 @@
 
         AssetManager assets = new AssetManager();
         try {
-            assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                     Build.VERSION.RESOURCES_SDK_INT);
             loadApkIntoAssetManager(assets, mBaseCodePath, mFlags);
 
diff --git a/core/java/android/content/pm/split/SplitAssetDependencyLoader.java b/core/java/android/content/pm/split/SplitAssetDependencyLoader.java
index 3ad45b6..4df90eb 100644
--- a/core/java/android/content/pm/split/SplitAssetDependencyLoader.java
+++ b/core/java/android/content/pm/split/SplitAssetDependencyLoader.java
@@ -83,7 +83,7 @@
             throws PackageParser.PackageParserException {
         final AssetManager assets = new AssetManager();
         try {
-            assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                     Build.VERSION.RESOURCES_SDK_INT);
 
             for (String assetPath : assetPaths) {
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index db24ffe..37e32ff 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StringRes;
+import android.content.pm.ActivityInfo;
 import android.content.res.Configuration.NativeConfig;
 import android.os.ParcelFileDescriptor;
 import android.util.Log;
@@ -183,6 +184,11 @@
             if (block < 0) {
                 return null;
             }
+
+            // Convert the changing configurations flags populated by native code.
+            outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
+                    outValue.changingConfigurations);
+
             if (outValue.type == TypedValue.TYPE_STRING) {
                 return mStringBlocks[block].get(outValue.data);
             }
@@ -220,6 +226,11 @@
         if (block < 0) {
             return false;
         }
+
+        // Convert the changing configurations flags populated by native code.
+        outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
+                outValue.changingConfigurations);
+
         if (outValue.type == TypedValue.TYPE_STRING) {
             outValue.string = mStringBlocks[block].get(outValue.data);
         }
@@ -266,6 +277,11 @@
         if (block < 0) {
             return false;
         }
+
+        // Convert the changing configurations flags populated by native code.
+        outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
+                outValue.changingConfigurations);
+
         if (outValue.type == TypedValue.TYPE_STRING) {
             final StringBlock[] blocks = ensureStringBlocks();
             outValue.string = blocks[block].get(outValue.data);
@@ -759,7 +775,7 @@
             int orientation, int touchscreen, int density, int keyboard,
             int keyboardHidden, int navigation, int screenWidth, int screenHeight,
             int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp,
-            int screenLayout, int uiMode, int majorVersion);
+            int screenLayout, int uiMode, int colorMode, int majorVersion);
 
     /**
      * Retrieve the resource identifier for the given resource name.
diff --git a/core/java/android/content/res/FontResourcesParser.java b/core/java/android/content/res/FontResourcesParser.java
new file mode 100644
index 0000000..15f3a09
--- /dev/null
+++ b/core/java/android/content/res/FontResourcesParser.java
@@ -0,0 +1,104 @@
+/*
+ * 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.content.res;
+
+import com.android.internal.R;
+import android.text.FontConfig;
+import android.util.AttributeSet;
+import android.util.Xml;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Parser for xml type font resources.
+ * @hide
+ */
+public class FontResourcesParser {
+    private static final int NORMAL_WEIGHT = 400;
+    private static final String ITALIC = "italic";
+
+    public static FontConfig parse(XmlPullParser parser, Resources resources)
+            throws XmlPullParserException, IOException {
+        int type;
+        while ((type=parser.next()) != XmlPullParser.START_TAG
+                && type != XmlPullParser.END_DOCUMENT) {
+            // Empty loop.
+        }
+
+        if (type != XmlPullParser.START_TAG) {
+            throw new XmlPullParserException("No start tag found");
+        }
+        return readFamilies(parser, resources);
+    }
+
+    private static FontConfig readFamilies(XmlPullParser parser, Resources resources)
+            throws XmlPullParserException, IOException {
+        FontConfig config = new FontConfig();
+        parser.require(XmlPullParser.START_TAG, null, "font-family");
+        String tag = parser.getName();
+        if (tag.equals("font-family")) {
+            config.getFamilies().add(readFamily(parser, resources));
+        } else {
+            skip(parser);
+        }
+        return config;
+    }
+
+    private static FontConfig.Family readFamily(XmlPullParser parser, Resources resources)
+            throws XmlPullParserException, IOException {
+        List<FontConfig.Font> fonts = new ArrayList<>();
+        while (parser.next() != XmlPullParser.END_TAG) {
+            if (parser.getEventType() != XmlPullParser.START_TAG) continue;
+            String tag = parser.getName();
+            if (tag.equals("font")) {
+                fonts.add(readFont(parser, resources));
+            } else {
+                skip(parser);
+            }
+        }
+        return new FontConfig.Family(null, fonts, null, null);
+    }
+
+    private static FontConfig.Font readFont(XmlPullParser parser, Resources resources)
+            throws XmlPullParserException, IOException {
+        AttributeSet attrs = Xml.asAttributeSet(parser);
+        TypedArray array = resources.obtainAttributes(attrs, R.styleable.FontFamilyFont);
+        int weight = array.getInt(R.styleable.FontFamilyFont_fontWeight, NORMAL_WEIGHT);
+        boolean isItalic = ITALIC.equals(array.getString(R.styleable.FontFamilyFont_fontStyle));
+        String filename = array.getString(R.styleable.FontFamilyFont_font);
+        array.recycle();
+        return new FontConfig.Font(filename, 0, null, weight, isItalic);
+    }
+
+    private static void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
+        int depth = 1;
+        while (depth > 0) {
+            switch (parser.next()) {
+                case XmlPullParser.START_TAG:
+                    depth++;
+                    break;
+                case XmlPullParser.END_TAG:
+                    depth--;
+                    break;
+            }
+        }
+    }
+}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index c3185a7..04e4454 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -27,6 +27,7 @@
 import android.annotation.ColorRes;
 import android.annotation.DimenRes;
 import android.annotation.DrawableRes;
+import android.annotation.FontRes;
 import android.annotation.FractionRes;
 import android.annotation.IntegerRes;
 import android.annotation.LayoutRes;
@@ -39,6 +40,7 @@
 import android.annotation.StyleableRes;
 import android.annotation.XmlRes;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ActivityInfo.Config;
 import android.graphics.Movie;
 import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
@@ -349,12 +351,12 @@
      *
      * @return Typeface The Typeface data associated with the resource.
      */
-    @NonNull public Typeface getFont(@StringRes int id) throws NotFoundException {
+    @NonNull public Typeface getFont(@FontRes int id) throws NotFoundException {
         final TypedValue value = obtainTempTypedValue();
         try {
             final ResourcesImpl impl = mResourcesImpl;
             impl.getValue(id, value, true);
-            Typeface typeface = impl.loadFont(value, id);
+            Typeface typeface = impl.loadFont(this, value, id);
             if (typeface != null) {
                 return typeface;
             }
@@ -365,6 +367,11 @@
                 + Integer.toHexString(id));
     }
 
+    @NonNull
+    Typeface getFont(@NonNull TypedValue value, @FontRes int id) throws NotFoundException {
+        return mResourcesImpl.loadFont(this, value, id);
+    }
+
     /**
      * Returns the character sequence necessary for grammatically correct pluralization
      * of the given resource ID for the given quantity.
@@ -1604,7 +1611,7 @@
          *         {@link ActivityInfo}
          * @see ActivityInfo
          */
-        public int getChangingConfigurations() {
+        public @Config int getChangingConfigurations() {
             return mThemeImpl.getChangingConfigurations();
         }
 
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 05892e0..3cf36d7 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -30,6 +30,7 @@
 import android.annotation.StyleableRes;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ActivityInfo.Config;
+import android.content.res.Configuration.NativeConfig;
 import android.content.res.Resources.NotFoundException;
 import android.graphics.Typeface;
 import android.graphics.drawable.ColorDrawable;
@@ -38,6 +39,7 @@
 import android.os.Build;
 import android.os.LocaleList;
 import android.os.Trace;
+import android.text.FontConfig;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -45,7 +47,6 @@
 import android.util.Slog;
 import android.util.TypedValue;
 import android.util.Xml;
-import android.view.Display;
 import android.view.DisplayAdjustments;
 
 import java.io.IOException;
@@ -420,7 +421,7 @@
                         mConfiguration.smallestScreenWidthDp,
                         mConfiguration.screenWidthDp, mConfiguration.screenHeightDp,
                         mConfiguration.screenLayout, mConfiguration.uiMode,
-                        Build.VERSION.RESOURCES_SDK_INT);
+                        mConfiguration.colorMode, Build.VERSION.RESOURCES_SDK_INT);
 
                 if (DEBUG_CONFIG) {
                     Slog.i(TAG, "**** Updating config of " + this + ": final config is "
@@ -745,13 +746,17 @@
      * Loads a font from XML or resources stream.
      */
     @Nullable
-    public Typeface loadFont(TypedValue value, int id) {
+    public Typeface loadFont(Resources wrapper, TypedValue value, int id) {
         if (value.string == null) {
             throw new NotFoundException("Resource \"" + getResourceName(id) + "\" ("
                     + Integer.toHexString(id) + ") is not a Font: " + value);
         }
 
         final String file = value.string.toString();
+        Typeface cached = Typeface.createFromCache(mAssets, file);
+        if (cached != null) {
+            return cached;
+        }
 
         if (DEBUG_LOAD) {
             Log.v(TAG, "Loading font for cookie " + value.assetCookie + ": " + file);
@@ -759,12 +764,17 @@
 
         Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
         try {
-            if (file.endsWith(".xml")) {
-                // TODO handle xml type font definitions
-            } else {
-                return Typeface.createFromResources(
-                        mAssets, value.string.toString(), value.assetCookie);
+            if (file.endsWith("xml")) {
+                final XmlResourceParser rp = loadXmlResourceParser(
+                        file, id, value.assetCookie, "font");
+                final FontConfig config = FontResourcesParser.parse(rp, wrapper);
+                return Typeface.createFromResources(config, mAssets, file);
             }
+            return Typeface.createFromResources(mAssets, file, value.assetCookie);
+        } catch (XmlPullParserException e) {
+            Log.e(TAG, "Failed to parse xml resource " + file, e);
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to read xml resource " + file, e);
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
         }
@@ -1197,7 +1207,7 @@
 
         @Config int getChangingConfigurations() {
             synchronized (mKey) {
-                final int nativeChangingConfig =
+                final @NativeConfig int nativeChangingConfig =
                         AssetManager.getThemeChangingConfigurations(mTheme);
                 return ActivityInfo.activityInfoConfigNativeToJava(nativeChangingConfig);
             }
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 3912201..f48afb5 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -22,6 +22,7 @@
 import android.annotation.StyleableRes;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ActivityInfo.Config;
+import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
 import android.os.StrictMode;
 import android.util.AttributeSet;
@@ -937,6 +938,36 @@
     }
 
     /**
+     * Retrieve the Typeface for the attribute at <var>index</var>.
+     * <p>
+     * This method will throw an exception if the attribute is defined but is
+     * not a font.
+     *
+     * @param index Index of attribute to retrieve.
+     *
+     * @return Typeface for the attribute, or {@code null} if not defined.
+     * @throws RuntimeException if the TypedArray has already been recycled.
+     * @throws UnsupportedOperationException if the attribute is defined but is
+     *         not a font resource.
+     */
+    @Nullable
+    public Typeface getFont(@StyleableRes int index) {
+        if (mRecycled) {
+            throw new RuntimeException("Cannot make calls to a recycled instance!");
+        }
+
+        final TypedValue value = mValue;
+        if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
+            if (value.type == TypedValue.TYPE_ATTRIBUTE) {
+                throw new UnsupportedOperationException(
+                        "Failed to resolve attribute at index " + index + ": " + value);
+            }
+            return mResources.getFont(value, value.resourceId);
+        }
+        return null;
+    }
+
+    /**
      * Retrieve the CharSequence[] for the attribute at <var>index</var>.
      * This gets the resource ID of the selected attribute, and uses
      * {@link Resources#getTextArray Resources.getTextArray} of the owning
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 227066d..8cd3d7b 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -728,13 +728,10 @@
      * @param values the {@link ContentValues} to put the row into.
      */
     public static void cursorRowToContentValues(Cursor cursor, ContentValues values) {
-        AbstractWindowedCursor awc =
-                (cursor instanceof AbstractWindowedCursor) ? (AbstractWindowedCursor) cursor : null;
-
         String[] columns = cursor.getColumnNames();
         int length = columns.length;
         for (int i = 0; i < length; i++) {
-            if (awc != null && awc.isBlob(i)) {
+            if (cursor.getType(i) == Cursor.FIELD_TYPE_BLOB) {
                 values.put(columns[i], cursor.getBlob(i));
             } else {
                 values.put(columns[i], cursor.getString(i));
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 98a8904..12b46c1 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1625,6 +1625,34 @@
             new Key<Integer>("android.control.postRawSensitivityBoost", int.class);
 
     /**
+     * <p>Allow camera device to enable zero-shutter-lag mode for requests with
+     * {@link CaptureRequest#CONTROL_CAPTURE_INTENT android.control.captureIntent} == STILL_CAPTURE.</p>
+     * <p>If enableZsl is <code>true</code>, the camera device may enable zero-shutter-lag mode for requests with
+     * STILL_CAPTURE capture intent. The camera device may use images captured in the past to
+     * produce output images for a zero-shutter-lag request. The result metadata including the
+     * {@link CaptureResult#SENSOR_TIMESTAMP android.sensor.timestamp} reflects the source frames used to produce output images.
+     * Therefore, the contents of the output images and the result metadata may be out of order
+     * compared to previous regular requests. enableZsl does not affect requests with other
+     * capture intents.</p>
+     * <p>For example, when requests are submitted in the following order:
+     *   Request A: enableZsl is ON, {@link CaptureRequest#CONTROL_CAPTURE_INTENT android.control.captureIntent} is PREVIEW
+     *   Request B: enableZsl is ON, {@link CaptureRequest#CONTROL_CAPTURE_INTENT android.control.captureIntent} is STILL_CAPTURE</p>
+     * <p>The output images for request B may have contents captured before the output images for
+     * request A, and the result metadata for request B may be older than the result metadata for
+     * request A.</p>
+     * <p>Note that when enableZsl is <code>true</code>, it is not guaranteed to get output images captured in the
+     * past for requests with STILL_CAPTURE capture intent.</p>
+     * <p>The value of enableZsl in capture templates is always <code>false</code> if present.</p>
+     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     *
+     * @see CaptureRequest#CONTROL_CAPTURE_INTENT
+     * @see CaptureResult#SENSOR_TIMESTAMP
+     */
+    @PublicKey
+    public static final Key<Boolean> CONTROL_ENABLE_ZSL =
+            new Key<Boolean>("android.control.enableZsl", boolean.class);
+
+    /**
      * <p>Operation mode for edge
      * enhancement.</p>
      * <p>Edge enhancement improves sharpness and details in the captured image. OFF means
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 23f4b9e..3f8b57a 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -2132,6 +2132,34 @@
             new Key<Integer>("android.control.postRawSensitivityBoost", int.class);
 
     /**
+     * <p>Allow camera device to enable zero-shutter-lag mode for requests with
+     * {@link CaptureRequest#CONTROL_CAPTURE_INTENT android.control.captureIntent} == STILL_CAPTURE.</p>
+     * <p>If enableZsl is <code>true</code>, the camera device may enable zero-shutter-lag mode for requests with
+     * STILL_CAPTURE capture intent. The camera device may use images captured in the past to
+     * produce output images for a zero-shutter-lag request. The result metadata including the
+     * {@link CaptureResult#SENSOR_TIMESTAMP android.sensor.timestamp} reflects the source frames used to produce output images.
+     * Therefore, the contents of the output images and the result metadata may be out of order
+     * compared to previous regular requests. enableZsl does not affect requests with other
+     * capture intents.</p>
+     * <p>For example, when requests are submitted in the following order:
+     *   Request A: enableZsl is ON, {@link CaptureRequest#CONTROL_CAPTURE_INTENT android.control.captureIntent} is PREVIEW
+     *   Request B: enableZsl is ON, {@link CaptureRequest#CONTROL_CAPTURE_INTENT android.control.captureIntent} is STILL_CAPTURE</p>
+     * <p>The output images for request B may have contents captured before the output images for
+     * request A, and the result metadata for request B may be older than the result metadata for
+     * request A.</p>
+     * <p>Note that when enableZsl is <code>true</code>, it is not guaranteed to get output images captured in the
+     * past for requests with STILL_CAPTURE capture intent.</p>
+     * <p>The value of enableZsl in capture templates is always <code>false</code> if present.</p>
+     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     *
+     * @see CaptureRequest#CONTROL_CAPTURE_INTENT
+     * @see CaptureResult#SENSOR_TIMESTAMP
+     */
+    @PublicKey
+    public static final Key<Boolean> CONTROL_ENABLE_ZSL =
+            new Key<Boolean>("android.control.enableZsl", boolean.class);
+
+    /**
      * <p>Operation mode for edge
      * enhancement.</p>
      * <p>Edge enhancement improves sharpness and details in the captured image. OFF means
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 79eac26..1887086 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -792,7 +792,8 @@
     private Location getGpsLocation() {
         String processingMethod = get(CaptureResult.JPEG_GPS_PROCESSING_METHOD);
         double[] coords = get(CaptureResult.JPEG_GPS_COORDINATES);
-        Long timeStamp = get(CaptureResult.JPEG_GPS_TIMESTAMP);
+        // Location expects timestamp in [ms.]
+        Long timeStamp = get(CaptureResult.JPEG_GPS_TIMESTAMP) * 1000;
 
         if (areValuesAllNull(processingMethod, coords, timeStamp)) {
             return null;
@@ -823,7 +824,8 @@
 
         double[] coords = { l.getLatitude(), l.getLongitude(), l.getAltitude() };
         String processMethod = translateLocationProviderToProcess(l.getProvider());
-        long timestamp = l.getTime();
+        //JPEG_GPS_TIMESTAMP expects sec. instead of msec.
+        long timestamp = l.getTime() / 1000;
 
         set(CaptureRequest.JPEG_GPS_TIMESTAMP, timestamp);
         set(CaptureRequest.JPEG_GPS_COORDINATES, coords);
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index 2d5c4ce..6b7546f 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -358,7 +358,12 @@
             throw new IllegalArgumentException("Exceeds maximum number of surfaces");
         }
 
-        if (!mConfiguredSize.equals(SurfaceUtils.getSurfaceSize(surface))) {
+        // TODO: b/34697112. This needs to be reverted once app fix is merged.
+        // Do not throw exception for below case:
+        // - OutputConfiguration(Size(0, 0), klass)
+        // - addSurface(surface)
+        if ((mConfiguredSize.getWidth() != 0 || mConfiguredSize.getHeight() != 0) &&
+                !mConfiguredSize.equals(SurfaceUtils.getSurfaceSize(surface))) {
             throw new IllegalArgumentException("The size of added surface doesn't match");
         }
         if (mConfiguredDataspace != SurfaceUtils.getSurfaceDataspace(surface)) {
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 12e1963..33a9f5e 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -108,13 +108,14 @@
      * </p>
      *
      * <p>
-     * A private virtual display belongs to the application that created it.
-     * Only the a owner of a private virtual display is allowed to place windows upon it.
-     * The private virtual display also does not participate in display mirroring: it will
-     * neither receive mirrored content from another display nor allow its own content to
-     * be mirrored elsewhere.  More precisely, the only processes that are allowed to
-     * enumerate or interact with the private display are those that have the same UID as the
-     * application that originally created the private virtual display.
+     * A private virtual display belongs to the application that created it.  Only the a owner of a
+     * private virtual display and the apps that are already on that display are allowed to place
+     * windows upon it.  The private virtual display also does not participate in display mirroring:
+     * it will neither receive mirrored content from another display nor allow its own content to be
+     * mirrored elsewhere.  More precisely, the only processes that are allowed to enumerate or
+     * interact with the private display are those that have the same UID as the application that
+     * originally created the private virtual display or as the activities that are already on that
+     * display.
      * </p>
      *
      * @see #createVirtualDisplay
@@ -234,6 +235,21 @@
      */
     public static final int VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR = 1 << 4;
 
+    /**
+     * Virtual display flag: Allows content to be displayed on private virtual displays when
+     * keyguard is shown but is insecure.
+     *
+     * <p>
+     * This flag can only be applied to private displays as defined by the
+     * {@link Display#FLAG_PRIVATE} display flag. It is mutually exclusive with
+     * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}. If both flags are specified then this flag's behavior
+     * will not be applied.
+     * </p>
+     *
+     * @see #createVirtualDisplay
+     */
+    public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5;
+
     /** @hide */
     public DisplayManager(Context context) {
         mContext = context;
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 4b57078..2c9e6c7 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -1074,7 +1074,7 @@
 
         @Override // binder call
         public void onAuthenticationFailed(long deviceId) {
-            mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();;
+            mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();
         }
 
         @Override // binder call
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index a9c09c4..bdb278b 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -81,4 +81,6 @@
 
     void setPointerIconType(int typeId);
     void setCustomPointerIcon(in PointerIcon icon);
+
+    void requestPointerCapture(IBinder windowToken, boolean enabled);
 }
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 2b0593f..6e202b0 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -40,6 +40,7 @@
 import android.util.SparseArray;
 import android.view.InputDevice;
 import android.view.InputEvent;
+import android.view.MotionEvent;
 import android.view.PointerIcon;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodSubtype;
@@ -898,6 +899,25 @@
         }
     }
 
+    /**
+     * Request or release pointer capture.
+     * <p>
+     * When in capturing mode, the pointer icon disappears and all mouse events are dispatched to
+     * the window which has requested the capture. Relative position changes are available through
+     * {@link MotionEvent#getX} and {@link MotionEvent#getY}.
+     *
+     * @param enable true when requesting pointer capture, false when releasing.
+     *
+     * @hide
+     */
+    public void requestPointerCapture(IBinder windowToken, boolean enable) {
+        try {
+            mIm.requestPointerCapture(windowToken, enable);
+        } catch (RemoteException ex) {
+            throw ex.rethrowFromSystemServer();
+        }
+    }
+
     private void populateInputDevicesLocked() {
         if (mInputDevicesChangedListener == null) {
             final InputDevicesChangedListener listener = new InputDevicesChangedListener();
diff --git a/core/java/android/hardware/usb/UsbEndpoint.java b/core/java/android/hardware/usb/UsbEndpoint.java
index 708d651..c346700 100644
--- a/core/java/android/hardware/usb/UsbEndpoint.java
+++ b/core/java/android/hardware/usb/UsbEndpoint.java
@@ -75,8 +75,8 @@
      * if the direction is host to device, and
      * {@link UsbConstants#USB_DIR_IN} if the
      * direction is device to host.
-     * @see {@link UsbConstants#USB_DIR_IN}
-     * @see {@link UsbConstants#USB_DIR_OUT}
+     * @see UsbConstants#USB_DIR_IN
+     * @see UsbConstants#USB_DIR_OUT
      *
      * @return the endpoint's direction
      */
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index c6338cb..beed6e9 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -2367,16 +2367,16 @@
         }
         return true;
     }
-    
+
     /**
      * Return text that can be used as a button label for the given
      * {@link EditorInfo#imeOptions EditorInfo.imeOptions}.  Returns null
      * if there is no action requested.  Note that there is no guarantee that
      * the returned text will be relatively short, so you probably do not
      * want to use it as text on a soft keyboard key label.
-     * 
-     * @param imeOptions The value from @link EditorInfo#imeOptions EditorInfo.imeOptions}.
-     * 
+     *
+     * @param imeOptions The value from {@link EditorInfo#imeOptions EditorInfo.imeOptions}.
+     *
      * @return Returns a label to use, or null if there is no action.
      */
     public CharSequence getTextForImeAction(int imeOptions) {
diff --git a/core/java/android/metrics/LogMaker.java b/core/java/android/metrics/LogMaker.java
index 2bf841c..0ee2574 100644
--- a/core/java/android/metrics/LogMaker.java
+++ b/core/java/android/metrics/LogMaker.java
@@ -102,10 +102,13 @@
 
     /**
      * @param tag From your MetricsEvent enum.
-     * @param value One of Integer, Long, Float, String
-     * @return
+     * @param value One of Integer, Long, Float, or String; or null to clear the tag.
+     * @return modified LogMaker
      */
     public LogMaker addTaggedData(int tag, Object value) {
+        if (value == null) {
+            return clearTaggedData(tag);
+        }
         if (!isValidValue(value)) {
             throw new IllegalArgumentException(
                     "Value must be loggable type - int, long, float, String");
@@ -118,11 +121,21 @@
         return this;
     }
 
+    /**
+     * Remove a value from the LogMaker.
+     *
+     * @param tag From your MetricsEvent enum.
+     * @return modified LogMaker
+     */
+    public LogMaker clearTaggedData(int tag) {
+        entries.delete(tag);
+        return this;
+    }
+
+    /**
+     * @return true if this object may be added to a LogMaker as a value.
+     */
     public boolean isValidValue(Object value) {
-        if (value == null) {
-            Log.i("LogBuilder", "Logging a null value.");
-            return true;
-        }
         return value instanceof Integer ||
             value instanceof String ||
             value instanceof Long ||
@@ -227,6 +240,9 @@
         return out;
     }
 
+    /**
+     * Reconstitute an object from the output of {@link #serialize()}.
+     */
     public void deserialize(Object[] items) {
         int i = 0;
         while (i < items.length) {
@@ -239,4 +255,22 @@
             }
         }
     }
+
+    /**
+     * @param that the object to compare to.
+     * @return true if values in that equal values in this, for tags that exist in this.
+     */
+    public boolean isSubsetOf(LogMaker that) {
+        if (that == null) {
+            return false;
+        }
+        for (int i = 0; i < entries.size(); i++) {
+            int key = this.entries.keyAt(i);
+            Object thisValue = this.entries.valueAt(i);
+            Object thatValue = that.entries.get(key);
+            if ((thisValue == null && thatValue != null) || !thisValue.equals(thatValue))
+                return false;
+        }
+        return true;
+    }
 }
diff --git a/core/java/android/net/NetworkBadging.java b/core/java/android/net/NetworkBadging.java
new file mode 100644
index 0000000..5cf2f96
--- /dev/null
+++ b/core/java/android/net/NetworkBadging.java
@@ -0,0 +1,152 @@
+/*
+ * 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;
+
+import android.annotation.DrawableRes;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.net.ScoredNetwork.Badging;
+import android.net.wifi.WifiManager;
+import android.view.View;
+
+/**
+ * Utility methods for working with network badging.
+ *
+ * TODO: move ScoredNetwork.Badging and related constants to this class.
+ *
+ * @hide
+ */
+@SystemApi
+public class NetworkBadging {
+    private NetworkBadging() {}
+
+    /**
+     * Returns a Wi-Fi icon for a network with a given signal level and badging value.
+     *
+     * @param signalLevel The level returned by {@link WifiManager#calculateSignalLevel(int, int)}
+     *                    for a network. Must be between 0 and {@link WifiManager#RSSI_LEVELS}-1.
+     * @param badging  {@see ScoredNetwork#Badging}, retrieved from
+     *                 {@link ScoredNetwork#calculateBadge(int)}.
+     * @param theme The theme for the current application, may be null.
+     * @return Drawable for the given icon
+     * @throws IllegalArgumentException if {@code signalLevel} is out of range or {@code badging}
+     *                                  is an invalid value
+     */
+    @NonNull public static Drawable getWifiIcon(
+            @IntRange(from=0, to=4) int signalLevel, @Badging int badging, @Nullable Theme theme) {
+        Resources resources = Resources.getSystem();
+        if (badging == ScoredNetwork.BADGING_NONE) {
+            return resources.getDrawable(getWifiSignalResource(signalLevel), theme);
+        }
+        Drawable[] layers = new Drawable[] {
+                resources.getDrawable(getBadgedWifiSignalResource(signalLevel), theme),
+                resources.getDrawable(getWifiBadgeResource(badging), theme)
+        };
+        return new LayerDrawable(layers);
+    }
+
+    /**
+     * Returns the wifi signal resource id for the given signal level.
+     *
+     * <p>This wifi signal resource is a wifi icon to be displayed by itself when there is no badge.
+     *
+     * @param signalLevel The level returned by {@link WifiManager#calculateSignalLevel(int, int)}
+     *                    for a network. Must be between 0 and {@link WifiManager#RSSI_LEVELS}-1.
+     * @return the @DrawableRes for the icon
+     * @throws IllegalArgumentException for an invalid signal level
+     * @hide
+     */
+    @DrawableRes private static int getWifiSignalResource(int signalLevel) {
+        switch (signalLevel) {
+            case 0:
+                return com.android.internal.R.drawable.ic_wifi_signal_0;
+            case 1:
+                return com.android.internal.R.drawable.ic_wifi_signal_1;
+            case 2:
+                return com.android.internal.R.drawable.ic_wifi_signal_2;
+            case 3:
+                return com.android.internal.R.drawable.ic_wifi_signal_3;
+            case 4:
+                return com.android.internal.R.drawable.ic_wifi_signal_4;
+            default:
+                throw new IllegalArgumentException("Invalid signal level: " + signalLevel);
+        }
+    }
+
+    /**
+     * Returns the badged wifi signal resource id for the given signal level.
+     *
+     * <p>This badged wifi signal resource should be displayed with the quality badge retrieved
+     * from {@link #getWifiBadgeResource(int)}. If there is no badge,
+     * {@link #getWifiBadgeResource(int)} should be used instead of this method.
+     *
+     * @param signalLevel The level returned by {@link WifiManager#calculateSignalLevel(int, int)}
+     *                    for a network. Must be between 0 and {@link WifiManager#RSSI_LEVELS}-1.
+     * @return the @DrawableRes for the icon
+     * @throws IllegalArgumentException for an invalid signal level
+     * @hide
+     */
+    @DrawableRes private static int getBadgedWifiSignalResource(int signalLevel) {
+        switch (signalLevel) {
+            case 0:
+                return com.android.internal.R.drawable.ic_signal_wifi_badged_0_bars;
+            case 1:
+                return com.android.internal.R.drawable.ic_signal_wifi_badged_1_bar;
+            case 2:
+                return com.android.internal.R.drawable.ic_signal_wifi_badged_2_bars;
+            case 3:
+                return com.android.internal.R.drawable.ic_signal_wifi_badged_3_bars;
+            case 4:
+                return com.android.internal.R.drawable.ic_signal_wifi_badged_4_bars;
+            default:
+                throw new IllegalArgumentException("Invalid signal level: " + signalLevel);
+        }
+    }
+
+    /**
+     * Returns the wifi quality badge resource id for the the given badging balue.
+     *
+     * <p>This badge should be displayed with the badge signal resource retrieved from
+     * {@link #getBadgedWifiSignalResource(int)}.
+     *
+     * @param badging {@see ScoredNetwork#Badging} from {@link ScoredNetwork#calculateBadge(int)}.
+     * @return the @DrawableRes for the icon or {@link View#NO_ID} for
+     *         {@link ScoredNetwork#BADGING_NONE}
+     * @throws IllegalArgumentException for an invalid badging value.
+     * @hide
+     */
+    @DrawableRes private static int getWifiBadgeResource(@Badging int badging) {
+        switch (badging) {
+            case ScoredNetwork.BADGING_NONE:
+                return View.NO_ID;
+            case ScoredNetwork.BADGING_SD:
+                return com.android.internal.R.drawable.ic_signal_wifi_badged_sd;
+            case ScoredNetwork.BADGING_HD:
+                return com.android.internal.R.drawable.ic_signal_wifi_badged_hd;
+            case ScoredNetwork.BADGING_4K:
+                return com.android.internal.R.drawable.ic_signal_wifi_badged_4k;
+            default:
+                throw new IllegalArgumentException("No resource found for badge: " + badging);
+        }
+    }
+}
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index 7396189..d5377c7 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -1747,8 +1747,8 @@
      * begin with and a scheme component cannot be found.
      *
      * @return normalized Uri (never null)
-     * @see {@link android.content.Intent#setData}
-     * @see {@link android.content.Intent#setDataAndNormalize}
+     * @see android.content.Intent#setData
+     * @see android.content.Intent#setDataAndNormalize
      */
     public Uri normalizeScheme() {
         String scheme = getScheme();
diff --git a/core/java/android/nfc/NdefRecord.java b/core/java/android/nfc/NdefRecord.java
index 83d17ba..bd32314 100644
--- a/core/java/android/nfc/NdefRecord.java
+++ b/core/java/android/nfc/NdefRecord.java
@@ -805,7 +805,7 @@
 
                 if (!mb && records.size() == 0 && !inChunk && !ignoreMbMe) {
                     throw new FormatException("expected MB flag");
-                } else if (mb && records.size() != 0 && !ignoreMbMe) {
+                } else if (mb && (records.size() != 0 || inChunk) && !ignoreMbMe) {
                     throw new FormatException("unexpected MB flag");
                 } else if (inChunk && il) {
                     throw new FormatException("unexpected IL flag in non-leading chunk");
@@ -839,6 +839,9 @@
 
                 if (cf && !inChunk) {
                     // first chunk
+                    if (typeLength == 0) {
+                        throw new FormatException("expected non-zero type length in first chunk");
+                    }
                     chunks.clear();
                     chunkTnf = tnf;
                 }
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 80ecf97..817cb5b 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -883,8 +883,11 @@
             SystemProperties.getInt("ro.debuggable", 0) == 1;
 
     /** {@hide} */
-    public static final boolean IS_ENG =
-            "eng".equals(getString("ro.build.type"));
+    public static final boolean IS_ENG = "eng".equals(TYPE);
+    /** {@hide} */
+    public static final boolean IS_USERDEBUG = "userdebug".equals(TYPE);
+    /** {@hide} */
+    public static final boolean IS_USER = "user".equals(TYPE);
 
     /**
      * Whether this build is running inside a container.
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 175d883..210ddb6 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -1119,8 +1119,8 @@
      * @hide
      */
     public static void startMethodTracing(String traceName, FileDescriptor fd,
-        int bufferSize, int flags) {
-        VMDebug.startMethodTracing(traceName, fd, bufferSize, flags, false, 0);
+        int bufferSize, int flags, boolean streamOutput) {
+        VMDebug.startMethodTracing(traceName, fd, bufferSize, flags, false, 0, streamOutput);
     }
 
     /**
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 4616af8..7cdb3ce 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -272,6 +272,11 @@
     }
 
     /** {@hide} */
+    public static File getDataMiscCeDirectory() {
+        return buildPath(getDataDirectory(), "misc_ce");
+    }
+
+    /** {@hide} */
     public static File getDataMiscCeDirectory(int userId) {
         return buildPath(getDataDirectory(), "misc_ce", String.valueOf(userId));
     }
@@ -380,6 +385,24 @@
     }
 
     /**
+     * Returns location of preloaded cache directory for package name
+     * @see #getDataPreloadsDirectory()
+     * {@hide}
+     */
+    public static File getDataPreloadsFileCacheDirectory(String packageName) {
+        return new File(getDataPreloadsFileCacheDirectory(), packageName);
+    }
+
+    /**
+     * Returns location of preloaded cache directory.
+     * @see #getDataPreloadsDirectory()
+     * {@hide}
+     */
+    public static File getDataPreloadsFileCacheDirectory() {
+        return new File(getDataPreloadsDirectory(), "file_cache");
+    }
+
+    /**
      * Return the primary shared/external storage directory. This directory may
      * not currently be accessible if it has been mounted by the user on their
      * computer, has been removed from the device, or some other problem has
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index d6688e3..a41f45b 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -189,6 +189,13 @@
     /** {@hide} */
     public static final int LAST_APPLICATION_CACHE_GID = 29999;
 
+    /** {@hide} */
+    public static final int MEDIA_AUDIO_GID = 1055;
+    /** {@hide} */
+    public static final int MEDIA_VIDEO_GID = 1056;
+    /** {@hide} */
+    public static final int MEDIA_IMAGE_GID = 1057;
+
     /**
      * Standard priority of application threads.
      * Use with {@link #setThreadPriority(int)} and
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index ae981b7..b9e4bad 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -40,6 +40,7 @@
 import dalvik.system.BlockGuard;
 import dalvik.system.CloseGuard;
 import dalvik.system.VMDebug;
+import dalvik.system.VMRuntime;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -423,7 +424,21 @@
              * disk operations but will likely expand in future releases.
              */
             public Builder detectAll() {
-                return enable(ALL_THREAD_DETECT_BITS);
+                detectDiskReads();
+                detectDiskWrites();
+                detectNetwork();
+
+                final int targetSdk = VMRuntime.getRuntime().getTargetSdkVersion();
+                if (targetSdk >= Build.VERSION_CODES.HONEYCOMB) {
+                    detectCustomSlowCalls();
+                }
+                if (targetSdk >= Build.VERSION_CODES.M) {
+                    detectResourceMismatches();
+                }
+                if (targetSdk >= Build.VERSION_CODES.O) {
+                    detectUnbufferedIo();
+                }
+                return this;
             }
 
             /**
@@ -722,18 +737,31 @@
              * but will likely expand in future releases.
              */
             public Builder detectAll() {
-                int flags = DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_CURSOR_LEAKS
-                        | DETECT_VM_CLOSABLE_LEAKS | DETECT_VM_REGISTRATION_LEAKS
-                        | DETECT_VM_FILE_URI_EXPOSURE | DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION
-                        | DETECT_VM_UNTAGGED_SOCKET;
+                detectLeakedSqlLiteObjects();
 
-                // TODO: always add DETECT_VM_CLEARTEXT_NETWORK once we have facility
-                // for apps to mark sockets that should be ignored
-                if (SystemProperties.getBoolean(CLEARTEXT_PROPERTY, false)) {
-                    flags |= DETECT_VM_CLEARTEXT_NETWORK;
+                final int targetSdk = VMRuntime.getRuntime().getTargetSdkVersion();
+                if (targetSdk >= Build.VERSION_CODES.HONEYCOMB) {
+                    detectActivityLeaks();
+                    detectLeakedClosableObjects();
                 }
-
-                return enable(flags);
+                if (targetSdk >= Build.VERSION_CODES.JELLY_BEAN) {
+                    detectLeakedRegistrationObjects();
+                }
+                if (targetSdk >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+                    detectFileUriExposure();
+                }
+                if (targetSdk >= Build.VERSION_CODES.M) {
+                    // TODO: always add DETECT_VM_CLEARTEXT_NETWORK once we have
+                    // facility for apps to mark sockets that should be ignored
+                    if (SystemProperties.getBoolean(CLEARTEXT_PROPERTY, false)) {
+                        detectCleartextNetwork();
+                    }
+                }
+                if (targetSdk >= Build.VERSION_CODES.O) {
+                    detectContentUriWithoutPermission();
+                    detectUntaggedSockets();
+                }
+                return this;
             }
 
             /**
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index c5c380c..388054d 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -66,6 +66,8 @@
     private final IUserManager mService;
     private final Context mContext;
 
+    private Boolean mIsManagedProfileCached;
+
     /**
      * @hide
      * No user restriction.
@@ -970,8 +972,14 @@
      */
     @SystemApi
     public boolean isManagedProfile() {
+        // No need for synchronization.  Once it becomes non-null, it'll be non-null forever.
+        // Worst case we might end up calling the AIDL method multiple times but that's fine.
+        if (mIsManagedProfileCached != null) {
+            return mIsManagedProfileCached;
+        }
         try {
-            return mService.isManagedProfile(UserHandle.myUserId());
+            mIsManagedProfileCached = mService.isManagedProfile(UserHandle.myUserId());
+            return mIsManagedProfileCached;
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
@@ -987,6 +995,9 @@
      */
     @SystemApi
     public boolean isManagedProfile(@UserIdInt int userId) {
+        if (userId == UserHandle.myUserId()) {
+            return isManagedProfile();
+        }
         try {
             return mService.isManagedProfile(userId);
         } catch (RemoteException re) {
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 5ac33a1..fa9f394 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -352,8 +352,8 @@
         if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
             argsForZygote.add("--enable-safemode");
         }
-        if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
-            argsForZygote.add("--enable-debugger");
+        if ((debugFlags & Zygote.DEBUG_ENABLE_JDWP) != 0) {
+            argsForZygote.add("--enable-jdwp");
         }
         if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
             argsForZygote.add("--enable-checkjni");
@@ -367,6 +367,9 @@
         if ((debugFlags & Zygote.DEBUG_NATIVE_DEBUGGABLE) != 0) {
             argsForZygote.add("--native-debuggable");
         }
+        if ((debugFlags & Zygote.DEBUG_JAVA_DEBUGGABLE) != 0) {
+            argsForZygote.add("--java-debuggable");
+        }
         if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
             argsForZygote.add("--enable-assert");
         }
@@ -379,9 +382,6 @@
         }
         argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
 
-        //TODO optionally enable debuger
-        //argsForZygote.add("--enable-debugger");
-
         // --setgroups is a comma-separated list
         if (gids != null && gids.length > 0) {
             StringBuilder sb = new StringBuilder();
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b92d293..f1bffd3 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -59,6 +59,7 @@
 import android.os.LocaleList;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.speech.tts.TextToSpeech;
@@ -163,13 +164,13 @@
      * In some cases, a matching Activity may not exist, so ensure you
      * safeguard against this.
      * <p>
-     * Input: {@link ConnectivityManager.EXTRA_TETHER_TYPE} should be included to specify which type
-     * of tethering should be checked. {@link ConnectivityManager.EXTRA_PROVISION_CALLBACK} should
+     * Input: {@link ConnectivityManager#EXTRA_TETHER_TYPE} should be included to specify which type
+     * of tethering should be checked. {@link ConnectivityManager#EXTRA_PROVISION_CALLBACK} should
      * contain a {@link ResultReceiver} which will be called back with a tether result code.
      * <p>
      * Output: The result of the provisioning check.
-     * {@link ConnectivityManager.TETHER_ERROR_NO_ERROR} if successful,
-     * {@link ConnectivityManager.TETHER_ERROR_PROVISION_FAILED} for failure.
+     * {@link ConnectivityManager#TETHER_ERROR_NO_ERROR} if successful,
+     * {@link ConnectivityManager#TETHER_ERROR_PROVISION_FAILED} for failure.
      *
      * @hide
      */
@@ -296,7 +297,6 @@
      * Input: Nothing.
      * <p>
      * Output: Nothing.
-     * @hide
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_MANAGE_EXTERNAL_SOURCES =
@@ -1274,10 +1274,14 @@
 
     /**
      * Activity Action: Show notification settings for a single app.
-     *
-     * Input: Optionally, {@link #EXTRA_CHANNEL_ID}, to highlight that channel.
+     * <p>
+     *     Input: {@link #EXTRA_APP_PACKAGE}, the package containing the channel to display.
+     *     Input: Optionally, {@link #EXTRA_CHANNEL_ID}, to highlight that channel.
+     * <p>
+     * Output: Nothing.
      * @hide
      */
+    @SystemApi
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_APP_NOTIFICATION_SETTINGS
             = "android.settings.APP_NOTIFICATION_SETTINGS";
@@ -5191,6 +5195,9 @@
          *
          * <p>1 = permit app installation via the system package installer intent
          * <p>0 = do not allow use of the package installer
+         * @deprecated Starting from {@link android.os.Build.VERSION_CODES#O}, apps should use
+         * {@link PackageManager#canRequestPackageInstalls()}
+         * @see PackageManager#canRequestPackageInstalls()
          */
         public static final String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
 
@@ -7651,6 +7658,13 @@
        public static final String LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS =
                 "location_background_throttle_interval_ms";
 
+        /**
+         * Packages that are whitelisted for background throttling (throttling will not be applied).
+         * @hide
+         */
+        public static final String LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST =
+            "location_background_throttle_package_whitelist";
+
        /**
         * Whether TV will switch to MHL port when a mobile device is plugged in.
         * (0 = false, 1 = true)
@@ -8171,6 +8185,14 @@
         public static final String WIFI_WAKEUP_ENABLED = "wifi_wakeup_enabled";
 
         /**
+         * Value to specify whether network quality scores and badging should be shown in the UI.
+         *
+         * Type: int (0 for false, 1 for true)
+         * @hide
+         */
+        public static final String NETWORK_SCORING_UI_ENABLED = "network_scoring_ui_enabled";
+
+        /**
          * Value to specify if network recommendations from
          * {@link com.android.server.NetworkScoreService} are enabled.
          *
@@ -8785,6 +8807,26 @@
                 BLUETOOTH_PAN_PRIORITY_PREFIX = "bluetooth_pan_priority_";
 
         /**
+         * Activity manager specific settings.
+         * This is encoded as a key=value list, separated by commas. Ex:
+         *
+         * "enforce_bg_check=true,max_cached_processes=24"
+         *
+         * The following keys are supported:
+         *
+         * <pre>
+         * enforce_bg_check                     (boolean)
+         * max_cached_processes                 (int)
+         * </pre>
+         *
+         * <p>
+         * Type: string
+         * @hide
+         * @see com.android.server.am.ActivityManagerConstants
+         */
+        public static final String ACTIVITY_MANAGER_CONSTANTS = "activity_manager_constants";
+
+        /**
          * Device Idle (Doze) specific settings.
          * This is encoded as a key=value list, separated by commas. Ex:
          *
@@ -8850,6 +8892,25 @@
         public static final String APP_IDLE_CONSTANTS = "app_idle_constants";
 
         /**
+         * Power manager specific settings.
+         * This is encoded as a key=value list, separated by commas. Ex:
+         *
+         * "no_cached_wake_locks=1"
+         *
+         * The following keys are supported:
+         *
+         * <pre>
+         * no_cached_wake_locks                 (boolean)
+         * </pre>
+         *
+         * <p>
+         * Type: string
+         * @hide
+         * @see com.android.server.power.PowerManagerConstants
+         */
+        public static final String POWER_MANAGER_CONSTANTS = "power_manager_constants";
+
+        /**
          * Alarm manager specific settings.
          * This is encoded as a key=value list, separated by commas. Ex:
          *
@@ -9398,7 +9459,7 @@
         /**
          * WFC mode on roaming network.
          * <p>
-         * Type: int - see {@link WFC_IMS_MODE} for values
+         * Type: int - see {@link #WFC_IMS_MODE} for values
          *
          * @hide
          */
@@ -9520,6 +9581,14 @@
         public static final String CONTACTS_DATABASE_WAL_ENABLED = "contacts_database_wal_enabled";
 
         /**
+         * Flag to enable the link to location permissions in location setting. Set to 0 to disable.
+         *
+         * @hide
+         */
+        public static final String LOCATION_SETTINGS_LINK_TO_PERMISSIONS_ENABLED =
+                "location_settings_link_to_permissions_enabled";
+
+        /**
          * Settings to backup. This is here so that it's in the same place as the settings
          * keys and easy to update.
          *
@@ -10070,6 +10139,12 @@
          * @hide
          */
         public static final String WARNING_TEMPERATURE = "warning_temperature";
+
+        /**
+         * Whether the diskstats logging task is enabled/disabled.
+         * @hide
+         */
+        public static final String ENABLE_DISKSTATS_LOGGING = "enable_diskstats_logging";
     }
 
     /**
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index e48a0d0..a8b094e 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -284,8 +284,6 @@
          * not.
          *
          * <P>Type: INTEGER (boolean)</P>
-         *
-         * @hide
          */
         public static final String BACKED_UP = "backed_up";
 
@@ -294,8 +292,6 @@
          * restored, 0 if not.
          *
          * <P>Type: INTEGER (boolean)</P>
-         *
-         * @hide
          */
         public static final String RESTORED = "restored";
 
@@ -305,19 +301,19 @@
          * if not.
          *
          * <P>Type: INTEGER (boolean)</P>
-         *
-         * @hide
          */
         public static final String ARCHIVED = "archived";
 
         /**
          * Flag to indicate the voicemail is a OMTP voicemail handled by the {@link
          * android.telephony.VisualVoicemailService}. The UI should only show OMTP voicemails from
-         * the current visual voicemail package.
+         * the current visual voicemail package. For example, the selection could be
+         * {@code WHERE (IS_OMTP_VOICEMAIL == 0) OR ( IS_OMTP_VOICEMAIL == 1 AND SOURCE_PACKAGE ==
+         * "current.vvm.package")}
          *
          * <P>Type: INTEGER (boolean)</P>
          *
-         * @hide
+         * @see android.telephony.TelephonyManager#getVisualVoicemailPackageName
          */
         public static final String IS_OMTP_VOICEMAIL = "is_omtp_voicemail";
 
diff --git a/core/java/android/service/autofill/AutoFillService.java b/core/java/android/service/autofill/AutoFillService.java
index c7c8321..1e4f90d 100644
--- a/core/java/android/service/autofill/AutoFillService.java
+++ b/core/java/android/service/autofill/AutoFillService.java
@@ -30,13 +30,19 @@
 import android.os.Message;
 import android.util.Log;
 import android.view.autofill.AutoFillId;
+import android.view.autofill.Dataset;
 import android.view.autofill.FillResponse;
 
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.SomeArgs;
 
-// TODO(b/33197203): improve javadoc (of both class and methods); in particular, make sure the
-// life-cycle (and how state could be maintained on server-side) is well documented.
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+//TODO(b/33197203): improve javadoc (of both class and methods); in particular, make sure the
+//life-cycle (and how state could be maintained on server-side) is well documented.
 
 /**
  * Top-level service of the current auto-fill service for a given user.
@@ -48,6 +54,9 @@
     private static final String TAG = "AutoFillService";
     static final boolean DEBUG = true; // TODO(b/33197203): set to false once stable
 
+    // TODO(b/33197203): check for device's memory size instead of DEBUG?
+    static final boolean DEBUG_PENDING_CALLBACKS = DEBUG;
+
     /**
      * The {@link Intent} that must be declared as handled by the service.
      * To be supported, the service must also require the
@@ -73,42 +82,79 @@
     // Internal bundle keys.
     /** @hide */ public static final String KEY_CALLBACK = "callback";
     /** @hide */ public static final String KEY_SAVABLE_IDS = "savable_ids";
+    /** @hide */ public static final String EXTRA_CRYPTO_OBJECT_ID = "crypto_object_id";
 
     // Prefix for public bundle keys.
     private static final String KEY_PREFIX = "android.service.autofill.extra.";
 
     /**
      * Key of the {@link Bundle} passed to methods such as
-     * {@link #onSaveRequest(AssistStructure, Bundle, CancellationSignal, SaveCallback)}
-     * containing the extras set by
+     * {@link #onSaveRequest(AssistStructure, Bundle, SaveCallback)} containing the extras set by
      * {@link android.view.autofill.FillResponse.Builder#setExtras(Bundle)}.
      */
     public static final String EXTRA_RESPONSE_EXTRAS = KEY_PREFIX + "RESPONSE_EXTRAS";
 
     /**
      * Key of the {@link Bundle} passed to methods such as
-     * {@link #onSaveRequest(AssistStructure, Bundle, CancellationSignal, SaveCallback)}
-     * containing the extras set by
+     * {@link #onSaveRequest(AssistStructure, Bundle, SaveCallback)} containing the extras set by
      * {@link android.view.autofill.Dataset.Builder#setExtras(Bundle)}.
      */
     public static final String EXTRA_DATASET_EXTRAS = KEY_PREFIX + "DATASET_EXTRAS";
 
+    /**
+     * Used to indicate the user selected an action that requires authentication.
+     */
+    public static final int FLAG_AUTHENTICATION_REQUESTED = 1 << 0;
+
+    /**
+     * Used to indicate the user authentication succeeded.
+     */
+    public static final int FLAG_AUTHENTICATION_SUCCESS = 1 << 1;
+
+    /**
+     * Used to indicate the user authentication failed.
+     */
+    public static final int FLAG_AUTHENTICATION_ERROR = 1 << 2;
+
+    /**
+     * Used when the service requested Fingerprint authentication but such option is not available.
+     */
+    public static final int FLAG_FINGERPRINT_AUTHENTICATION_NOT_AVAILABLE  = 1 << 3;
+
     // Handler messages.
     private static final int MSG_CONNECT = 1;
-    private static final int MSG_AUTO_FILL_ACTIVITY = 2;
-    private static final int MSG_DISCONNECT = 3;
+    private static final int MSG_DISCONNECT = 2;
+    private static final int MSG_AUTO_FILL_ACTIVITY = 3;
+    private static final int MSG_AUTHENTICATE_FILL_RESPONSE = 4;
+    private static final int MSG_AUTHENTICATE_DATASET = 5;
 
     private final IAutoFillService mInterface = new IAutoFillService.Stub() {
 
         @Override
         public void autoFill(AssistStructure structure, IAutoFillServerCallback callback,
-                Bundle extras, int flags) {
+                int flags) {
             mHandlerCaller
-                    .obtainMessageIOOO(MSG_AUTO_FILL_ACTIVITY, flags, structure, extras, callback)
+                    .obtainMessageIOO(MSG_AUTO_FILL_ACTIVITY, flags, structure, callback)
                     .sendToTarget();
         }
 
         @Override
+        public void authenticateFillResponse(Bundle extras, int flags) {
+            final Message msg = mHandlerCaller.obtainMessage(MSG_AUTHENTICATE_FILL_RESPONSE);
+            msg.arg1 = flags;
+            msg.obj = extras;
+            mHandlerCaller.sendMessage(msg);
+        }
+
+        @Override
+        public void authenticateDataset(Bundle extras, int flags) {
+            final Message msg = mHandlerCaller.obtainMessage(MSG_AUTHENTICATE_DATASET);
+            msg.arg1 = flags;
+            msg.obj = extras;
+            mHandlerCaller.sendMessage(msg);
+        }
+
+        @Override
         public void onConnected() {
             mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_CONNECT));
         }
@@ -131,9 +177,18 @@
                     final SomeArgs args = (SomeArgs) msg.obj;
                     final int flags = msg.arg1;
                     final AssistStructure structure = (AssistStructure) args.arg1;
-                    final Bundle extras = (Bundle) args.arg2;
-                    final IAutoFillServerCallback callback = (IAutoFillServerCallback) args.arg3;
-                    requestAutoFill(callback, structure, extras, flags);
+                    final IAutoFillServerCallback callback = (IAutoFillServerCallback) args.arg2;
+                    requestAutoFill(callback, structure, flags);
+                    break;
+                } case MSG_AUTHENTICATE_FILL_RESPONSE: {
+                    final int flags = msg.arg1;
+                    final Bundle extras = (Bundle) msg.obj;
+                    onFillResponseAuthenticationRequest(extras, flags);
+                    break;
+                } case MSG_AUTHENTICATE_DATASET: {
+                    final int flags = msg.arg1;
+                    final Bundle extras = (Bundle) msg.obj;
+                    onDatasetAuthenticationRequest(extras, flags);
                     break;
                 } case MSG_DISCONNECT: {
                     onDisconnected();
@@ -147,6 +202,10 @@
 
     private HandlerCaller mHandlerCaller;
 
+    // User for debugging purposes
+    private final List<CallbackHelper.Dumpable> mPendingCallbacks =
+            DEBUG_PENDING_CALLBACKS ? new ArrayList<>() : null;
+
     /**
      * {@inheritDoc}
      *
@@ -192,8 +251,8 @@
      * @param cancellationSignal signal for observing cancel requests.
      * @param callback object used to notify the result of the request.
      */
-    public abstract void onFillRequest(AssistStructure structure,
-            Bundle data, CancellationSignal cancellationSignal, FillCallback callback);
+    public abstract void onFillRequest(AssistStructure structure, Bundle data,
+            CancellationSignal cancellationSignal, FillCallback callback);
 
     /**
      * Called when user requests service to save the fields of an {@link Activity}.
@@ -205,28 +264,112 @@
      * @param structure {@link Activity}'s view structure.
      * @param data bundle containing additional arguments set by the Android system (currently none)
      * or data passed by the service in the {@link FillResponse} that originated this call.
-     * @param cancellationSignal signal for observing cancel requests.
      * @param callback object used to notify the result of the request.
      */
-    public abstract void onSaveRequest(AssistStructure structure,
-            Bundle data, CancellationSignal cancellationSignal, SaveCallback callback);
+    public abstract void onSaveRequest(AssistStructure structure, Bundle data,
+            SaveCallback callback);
+
+    /**
+     * Called as result of the user action for a {@link FillResponse} that required authentication.
+     *
+     * <p>When the {@link FillResponse} required authentication through
+     * {@link android.view.autofill.FillResponse.Builder#requiresCustomAuthentication(Bundle, int)},
+     * this call indicates the user is requesting the service to authenticate him/her (and
+     * {@code flags} contains {@link #FLAG_AUTHENTICATION_REQUESTED}), and {@code extras} contains
+     * the {@link Bundle} passed to that method.
+     *
+     * <p>When the {@link FillResponse} required authentication through
+     * {@link android.view.autofill.FillResponse.Builder#requiresFingerprintAuthentication(
+     * android.hardware.fingerprint.FingerprintManager.CryptoObject, Bundle, int)},
+     * {@code flags} this call contains the result of the fingerprint authentication (such as
+     * {@link #FLAG_AUTHENTICATION_SUCCESS}, {@link #FLAG_AUTHENTICATION_ERROR}, and
+     * {@link #FLAG_FINGERPRINT_AUTHENTICATION_NOT_AVAILABLE}) and {@code extras} contains the
+     * {@link Bundle} passed to that method.
+     */
+    public void onFillResponseAuthenticationRequest(@SuppressWarnings("unused") Bundle extras,
+            int flags) {
+        if (DEBUG) Log.d(TAG, "onFillResponseAuthenticationRequest(): flags=" + flags);
+    }
+
+    /**
+     * Called as result of the user action for a {@link Dataset} that required authentication.
+     *
+     * <p>When the {@link Dataset} required authentication through
+     * {@link android.view.autofill.Dataset.Builder#requiresCustomAuthentication(Bundle, int)}, this
+     * call indicates the user is requesting the service to authenticate him/her (and {@code flags}
+     * contains {@link #FLAG_AUTHENTICATION_REQUESTED}), and {@code extras} contains the
+     * {@link Bundle} passed to that method.
+     *
+     * <p>When the {@link Dataset} required authentication through
+     * {@link android.view.autofill.Dataset.Builder#requiresFingerprintAuthentication(
+     * android.hardware.fingerprint.FingerprintManager.CryptoObject, Bundle, int)},
+     * {@code flags} this call contains the result of the fingerprint authentication (such as
+     * {@link #FLAG_AUTHENTICATION_SUCCESS}, {@link #FLAG_AUTHENTICATION_ERROR}, and
+     * {@link #FLAG_FINGERPRINT_AUTHENTICATION_NOT_AVAILABLE}) and {@code extras} contains the
+     * {@link Bundle} passed to that method.
+     */
+    public void onDatasetAuthenticationRequest(@SuppressWarnings("unused") Bundle extras,
+            int flags) {
+        if (DEBUG) Log.d(TAG, "onDatasetAuthenticationRequest(): flags=" + flags);
+    }
+
+    // TODO(b/33197203): make it final and create another method classes could extend so it's
+    // guaranteed to dump the pending callbacks?
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mPendingCallbacks != null) {
+            pw.print("Number of pending callbacks: "); pw.println(mPendingCallbacks.size());
+            final String prefix = "  ";
+            for (int i = 0; i < mPendingCallbacks.size(); i++) {
+                final CallbackHelper.Dumpable cb = mPendingCallbacks.get(i);
+                pw.print('#'); pw.print(i + 1); pw.println(':');
+                cb.dump(prefix, pw);
+            }
+            pw.println();
+        } else {
+            pw.println("Dumping disabled");
+        }
+    }
 
     private void requestAutoFill(IAutoFillServerCallback callback, AssistStructure structure,
-            Bundle data, int flags) {
-        switch (flags) {
-            case AUTO_FILL_FLAG_TYPE_FILL:
-                final FillCallback fillCallback = new FillCallback(callback);
-                // TODO(b/33197203): hook up the cancelationSignal
-                onFillRequest(structure, data, new CancellationSignal(), fillCallback);
-                break;
-            case AUTO_FILL_FLAG_TYPE_SAVE:
-                final SaveCallback saveCallback = new SaveCallback(callback);
-                // TODO(b/33197203): hook up the cancelationSignal
-                onSaveRequest(structure, data, new CancellationSignal(), saveCallback);
-                break;
-            default:
-                Log.w(TAG, "invalid flag on requestAutoFill(): " + flags);
+            int flags) {
+        if (DEBUG) Log.d(TAG, "requestAutoFill(): flags=" + flags);
+
+        if ((flags & AUTO_FILL_FLAG_TYPE_FILL) != 0) {
+            final FillCallback fillCallback = new FillCallback(callback);
+            if (DEBUG_PENDING_CALLBACKS) {
+                addPendingCallback(fillCallback);
+            }
+            // TODO(b/33197203): hook up the cancelationSignal
+            onFillRequest(structure, null, new CancellationSignal(), fillCallback);
+            return;
         }
+        if ((flags & AUTO_FILL_FLAG_TYPE_SAVE) != 0) {
+            final SaveCallback saveCallback = new SaveCallback(callback);
+            if (DEBUG_PENDING_CALLBACKS) {
+                addPendingCallback(saveCallback);
+            }
+            onSaveRequest(structure, null, saveCallback);
+            return;
+        }
+
+        Log.w(TAG, "invalid flags on requestAutoFill(): " + flags);
+    }
+
+    private void addPendingCallback(CallbackHelper.Dumpable callback) {
+        if (mPendingCallbacks == null) {
+            // Shouldn't happend since call is controlled by DEBUG_PENDING_CALLBACKS guard.
+            Log.wtf(TAG, "addPendingCallback(): mPendingCallbacks not set");
+            return;
+        }
+
+        if (DEBUG) Log.d(TAG, "Adding pending callback: " + callback);
+
+        callback.setFinalizer(() -> {
+            if (DEBUG) Log.d(TAG, "Removing pending callback: " + callback);
+            mPendingCallbacks.remove(callback);
+        });
+        mPendingCallbacks.add(callback);
     }
 
     /**
diff --git a/core/java/com/android/internal/logging/legacy/SysuiQueryParser.java b/core/java/android/service/autofill/CallbackHelper.java
similarity index 61%
rename from core/java/com/android/internal/logging/legacy/SysuiQueryParser.java
rename to core/java/android/service/autofill/CallbackHelper.java
index 7b3c0a7..ded8f97 100644
--- a/core/java/com/android/internal/logging/legacy/SysuiQueryParser.java
+++ b/core/java/android/service/autofill/CallbackHelper.java
@@ -13,20 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.internal.logging.legacy;
+package android.service.autofill;
 
-/**
- * Parse the Android framework sysui search query logs.
- * For now just treat them like actions.
- * @hide
- */
-public class SysuiQueryParser extends SysuiActionParser {
-    private static final String TAG = "SysuiQueryParser";
+import java.io.PrintWriter;
 
-    private static final int EVENTLOG_TAG = 524289;
+final class CallbackHelper {
 
-    @Override
-    public int getTag() {
-        return EVENTLOG_TAG;
+    static interface Dumpable {
+        void dump(String prefix, PrintWriter pw);
+        void setFinalizer(Finalizer f);
+    }
+
+    static interface Finalizer {
+        void gone();
     }
 }
diff --git a/core/java/android/service/autofill/FillCallback.java b/core/java/android/service/autofill/FillCallback.java
index 925da8b..7cab7ae 100644
--- a/core/java/android/service/autofill/FillCallback.java
+++ b/core/java/android/service/autofill/FillCallback.java
@@ -17,27 +17,49 @@
 package android.service.autofill;
 
 import static android.service.autofill.AutoFillService.DEBUG;
+import static android.util.DebugUtils.flagsToString;
 
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.os.Bundle;
 import android.os.RemoteException;
+import android.service.autofill.CallbackHelper.Dumpable;
+import android.service.autofill.CallbackHelper.Finalizer;
 import android.util.Log;
+import android.view.autofill.Dataset;
 import android.view.autofill.FillResponse;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
 
+import java.io.PrintWriter;
+
 /**
  * Handles auto-fill requests from the {@link AutoFillService} into the {@link Activity} being
  * auto-filled.
+ *
+ * <p>This class is thread safe.
  */
-public final class FillCallback {
+public final class FillCallback implements Dumpable {
 
     private static final String TAG = "FillCallback";
 
+    // NOTE: constants below are public so they can be used by flagsToString()
+    /** @hide */ public static final int STATE_INITIAL = 1 << 0;
+    /** @hide */ public static final int STATE_WAITING_FILL_RESPONSE_AUTH_RESPONSE = 1 << 1;
+    /** @hide */ public static final int STATE_WAITING_DATASET_AUTH_RESPONSE = 1 << 2;
+    /** @hide */ public static final int STATE_FINISHED_OK = 1 << 3;
+    /** @hide */ public static final int STATE_FINISHED_FAILURE = 1 << 4;
+    /** @hide */ public static final int STATE_FINISHED_ERROR = 1 << 5;
+    /** @hide */ public static final int STATE_FINISHED_AUTHENTICATED = 1 << 6;
+
     private final IAutoFillServerCallback mCallback;
 
-    private boolean mReplied = false;
+    @GuardedBy("mCallback")
+    private int mState = STATE_INITIAL;
+
+    @GuardedBy("mCallback")
+    private Finalizer mFinalizer;
 
     /** @hide */
     FillCallback(IAutoFillServerCallback callback) {
@@ -46,51 +68,174 @@
 
     /**
      * Notifies the Android System that an
-     * {@link AutoFillService#onFillRequest(android.app.assist.AssistStructure, Bundle, android.os.CancellationSignal, FillCallback)}
-     * was successfully fulfilled by the service.
+     * {@link AutoFillService#onFillRequest(android.app.assist.AssistStructure, Bundle,
+     * android.os.CancellationSignal, FillCallback)} was successfully fulfilled by the service.
      *
      * @param response auto-fill information for that activity, or {@code null} when the activity
-     * cannot be auto-filled (for example, if it only contains read-only fields).
-     *
-     * @throws RuntimeException if an error occurred while calling the Android System.
+     * cannot be auto-filled (for example, if it only contains read-only fields). See
+     * {@link FillResponse} for examples.
      */
     public void onSuccess(@Nullable FillResponse response) {
-        if (DEBUG) Log.d(TAG, "onSuccess(): respose=" + response);
+        final boolean authRequired = response != null && response.isAuthRequired();
 
-        checkNotRepliedYet();
+        if (DEBUG) Log.d(TAG, "onSuccess(): authReq= " + authRequired + ", resp=" + response);
 
-        try {
-            mCallback.showResponse(response);
-        } catch (RemoteException e) {
-            e.rethrowAsRuntimeException();
+        synchronized (mCallback) {
+            if (authRequired) {
+                assertOnStateLocked(STATE_INITIAL);
+            } else {
+                assertOnStateLocked(STATE_INITIAL | STATE_WAITING_FILL_RESPONSE_AUTH_RESPONSE
+                        | STATE_WAITING_DATASET_AUTH_RESPONSE);
+            }
+
+            try {
+                mCallback.showResponse(response);
+                if (authRequired) {
+                    mState = STATE_WAITING_FILL_RESPONSE_AUTH_RESPONSE;
+                } else {
+                    // Check if at least one dataset requires authentication.
+                    boolean waitingAuth = false;
+                    if (response != null) {
+                        for (Dataset dataset : response.getDatasets()) {
+                            if (dataset.isAuthRequired()) {
+                                waitingAuth = true;
+                                break;
+                            }
+                        }
+                    }
+                    if (waitingAuth) {
+                        mState = STATE_WAITING_DATASET_AUTH_RESPONSE;
+                    } else {
+                        setFinalStateLocked(STATE_FINISHED_OK);
+                    }
+                }
+            } catch (RemoteException e) {
+                setFinalStateLocked(STATE_FINISHED_ERROR);
+                e.rethrowAsRuntimeException();
+            }
         }
     }
 
     /**
      * Notifies the Android System that an
-     * {@link AutoFillService#onFillRequest(android.app.assist.AssistStructure, Bundle, android.os.CancellationSignal, FillCallback)}
+     * {@link AutoFillService#onFillRequest(android.app.assist.AssistStructure,
+     * Bundle, android.os.CancellationSignal, FillCallback)}
      * could not be fulfilled by the service.
      *
      * @param message error message to be displayed to the user.
-     *
-     * @throws RuntimeException if an error occurred while calling the Android System.
      */
     public void onFailure(CharSequence message) {
         if (DEBUG) Log.d(TAG, "onFailure(): message=" + message);
 
-        checkNotRepliedYet();
         Preconditions.checkArgument(message != null, "message cannot be null");
 
-        try {
-            mCallback.showError(message.toString());
-        } catch (RemoteException e) {
-            e.rethrowAsRuntimeException();
+        synchronized (mCallback) {
+            assertOnStateLocked(STATE_INITIAL | STATE_WAITING_FILL_RESPONSE_AUTH_RESPONSE
+                    | STATE_WAITING_DATASET_AUTH_RESPONSE);
+
+            try {
+                mCallback.showError(message);
+                setFinalStateLocked(STATE_FINISHED_FAILURE);
+            } catch (RemoteException e) {
+                setFinalStateLocked(STATE_FINISHED_ERROR);
+                e.rethrowAsRuntimeException();
+            }
         }
     }
 
-    // There can be only one!!
-    private void checkNotRepliedYet() {
-        Preconditions.checkState(!mReplied, "already replied");
-        mReplied = true;
+    /**
+     * Notifies the Android System when the user authenticated a {@link FillResponse} previously
+     * passed to {@link #onSuccess(FillResponse)}.
+     *
+     * @param flags must contain either
+     * {@link android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_ERROR} or
+     * {@link android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_SUCCESS}.
+     */
+    public void onFillResponseAuthentication(int flags) {
+        if (DEBUG) Log.d(TAG, "onFillResponseAuthentication(): flags=" + flags);
+
+        synchronized (mCallback) {
+            assertOnStateLocked(STATE_WAITING_FILL_RESPONSE_AUTH_RESPONSE);
+
+            try {
+                mCallback.unlockFillResponse(flags);
+                setFinalStateLocked(STATE_FINISHED_AUTHENTICATED);
+            } catch (RemoteException e) {
+                setFinalStateLocked(STATE_FINISHED_ERROR);
+                e.rethrowAsRuntimeException();
+            }
+        }
+    }
+
+    /**
+     * Notifies the Android System when the user authenticated a {@link Dataset} previously passed
+     * to {@link #onSuccess(FillResponse)}.
+     *
+     * @param dataset values to fill the activity with in case of successful authentication of a
+     * previously locked (and empty) dataset).
+     * @param flags must contain either
+     * {@link android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_ERROR} or
+     * {@link android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_SUCCESS}.
+     */
+    public void onDatasetAuthentication(@Nullable Dataset dataset, int flags) {
+        if (DEBUG) Log.d(TAG, "onDatasetAuthentication(): dataset=" + dataset + ", flags=" + flags);
+
+        synchronized (mCallback) {
+            assertOnStateLocked(STATE_WAITING_DATASET_AUTH_RESPONSE);
+
+            try {
+                mCallback.unlockDataset(dataset, flags);
+                setFinalStateLocked(STATE_FINISHED_AUTHENTICATED);
+            } catch (RemoteException e) {
+                setFinalStateLocked(STATE_FINISHED_ERROR);
+                e.rethrowAsRuntimeException();
+            }
+        }
+    }
+
+    @Override
+    public String toString() {
+        if (!DEBUG) return super.toString();
+
+        return "FillCallback: [mState = " + mState + "]";
+    }
+
+    /** @hide */
+    @Override
+    public void dump(String prefix, PrintWriter pw) {
+        pw.print(prefix); pw.print("FillCallback: mState="); pw.println(mState);
+    }
+
+    /** @hide */
+    @Override
+    public void setFinalizer(Finalizer f) {
+        synchronized (mCallback) {
+            mFinalizer = f;
+        }
+    }
+
+    /**
+     * Sets a final state (where the callback cannot be used anymore) and notifies the
+     * {@link Finalizer} (if any).
+     */
+    private void setFinalStateLocked(int state) {
+        if (DEBUG) Log.d(TAG, "setFinalState(): " + state);
+        mState = state;
+
+        if (mFinalizer != null) {
+            mFinalizer.gone();
+        }
+    }
+
+    // TODO(b/33197203): move and/or re-add state check logic on server side to avoid malicious app
+    // calling the callback on wrong state.
+
+    // Make sure callback method is called during the proper lifecycle state.
+    private void assertOnStateLocked(int flags) {
+        if (DEBUG) Log.d(TAG, "assertOnState(): current=" + mState + ", required=" + flags);
+
+        Preconditions.checkState((flags & mState) != 0,
+                "invalid state: required " + flagsToString(FillCallback.class, "STATE_", flags)
+                + ", current is " + flagsToString(FillCallback.class, "STATE_", mState));
     }
 }
diff --git a/core/java/android/service/autofill/IAutoFillAppCallback.aidl b/core/java/android/service/autofill/IAutoFillAppCallback.aidl
index 629b1f0..8c3898a 100644
--- a/core/java/android/service/autofill/IAutoFillAppCallback.aidl
+++ b/core/java/android/service/autofill/IAutoFillAppCallback.aidl
@@ -21,8 +21,14 @@
 import android.view.autofill.Dataset;
 
 /**
+ * Object running in the application process and responsible for auto-filling it.
+ *
  * @hide
  */
+// TODO(b/33197203): rename IAutoFillAppSession
 oneway interface IAutoFillAppCallback {
+    /**
+      * Auto-fills the activity with the contents of a dataset.
+      */
     void autoFill(in Dataset dataset);
 }
diff --git a/core/java/android/service/autofill/IAutoFillManagerService.aidl b/core/java/android/service/autofill/IAutoFillManagerService.aidl
index ce42107..ace5411 100644
--- a/core/java/android/service/autofill/IAutoFillManagerService.aidl
+++ b/core/java/android/service/autofill/IAutoFillManagerService.aidl
@@ -27,8 +27,9 @@
  */
 oneway interface IAutoFillManagerService {
 
-    void showAutoFillInput(in AutoFillId id, in Rect boundaries);
+    // Called by AutoFillManager (app).
+    void requestAutoFill(in AutoFillId id, in Rect bounds, int flags);
 
-    // TODO(b/33197203): remove it and refactor onShellCommand
-    void requestAutoFill(IBinder activityToken, int userId, in Bundle extras, int flags);
+    // Called by ShellCommand only.
+    void requestAutoFillForUser(int userId, int flags);
 }
diff --git a/core/java/android/service/autofill/IAutoFillServerCallback.aidl b/core/java/android/service/autofill/IAutoFillServerCallback.aidl
index 9d58c99..f7d5064 100644
--- a/core/java/android/service/autofill/IAutoFillServerCallback.aidl
+++ b/core/java/android/service/autofill/IAutoFillServerCallback.aidl
@@ -18,14 +18,22 @@
 
 import java.util.List;
 
+import android.os.Bundle;
 import android.view.autofill.AutoFillId;
+import android.view.autofill.Dataset;
 import android.view.autofill.FillResponse;
 
 /**
+ * Object running in the AutoFillService process and used to communicate back with system_server.
+ *
  * @hide
  */
+// TODO(b/33197203): rename to IAutoFillServerSession
 oneway interface IAutoFillServerCallback {
+    // TODO(b/33197203): document methods
     void showResponse(in FillResponse response);
-    void showError(String message);
+    void showError(CharSequence message);
     void highlightSavedFields(in AutoFillId[] ids);
+    void unlockFillResponse(int flags);
+    void unlockDataset(in Dataset dataset, int flags);
 }
diff --git a/core/java/android/service/autofill/IAutoFillService.aidl b/core/java/android/service/autofill/IAutoFillService.aidl
index a1f22bf..3e8087b 100644
--- a/core/java/android/service/autofill/IAutoFillService.aidl
+++ b/core/java/android/service/autofill/IAutoFillService.aidl
@@ -24,9 +24,12 @@
 /**
  * @hide
  */
+// TODO(b/33197203): document class and methods
 oneway interface IAutoFillService {
-    void autoFill(in AssistStructure structure, in IAutoFillServerCallback callback,
-                  in Bundle extras, int flags);
+    // TODO(b/33197203): rename method to make them more consistent
+    void autoFill(in AssistStructure structure, in IAutoFillServerCallback callback, int flags);
+    void authenticateFillResponse(in Bundle extras, int flags);
+    void authenticateDataset(in Bundle extras, int flags);
     void onConnected();
     void onDisconnected();
 }
diff --git a/core/java/android/service/autofill/SaveCallback.java b/core/java/android/service/autofill/SaveCallback.java
index 04f8c9f..e2fb588 100644
--- a/core/java/android/service/autofill/SaveCallback.java
+++ b/core/java/android/service/autofill/SaveCallback.java
@@ -22,23 +22,34 @@
 import android.app.assist.AssistStructure.ViewNode;
 import android.os.Bundle;
 import android.os.RemoteException;
+import android.service.autofill.CallbackHelper.Dumpable;
+import android.service.autofill.CallbackHelper.Finalizer;
 import android.util.Log;
 import android.view.autofill.AutoFillId;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
 
+import java.io.PrintWriter;
+
 /**
  * Handles save requests from the {@link AutoFillService} into the {@link Activity} being
  * auto-filled.
+ *
+ * <p>This class is thread safe.
  */
-public final class SaveCallback {
+public final class SaveCallback implements Dumpable {
 
     private static final String TAG = "SaveCallback";
 
     private final IAutoFillServerCallback mCallback;
 
+    @GuardedBy("mCallback")
     private boolean mReplied = false;
 
+    @GuardedBy("mCallback")
+    private Finalizer mFinalizer;
+
     /** @hide */
     SaveCallback(IAutoFillServerCallback callback) {
         mCallback = callback;
@@ -46,8 +57,8 @@
 
     /**
      * Notifies the Android System that an
-     * {@link AutoFillService#onSaveRequest(android.app.assist.AssistStructure, Bundle, android.os.CancellationSignal, SaveCallback)}
-     * was successfully fulfilled by the service.
+     * {@link AutoFillService#onSaveRequest(android.app.assist.AssistStructure, Bundle,
+     * SaveCallback)} was successfully fulfilled by the service.
      *
      * @param ids ids ({@link ViewNode#getAutoFillId()}) of the fields that were saved.
      *
@@ -57,21 +68,24 @@
         if (DEBUG) Log.d(TAG, "onSuccess(): ids=" + ((ids == null) ? "null" : ids.length));
 
         Preconditions.checkArgument(ids != null, "ids cannot be null");
-        checkNotRepliedYet();
-
         Preconditions.checkArgument(ids.length > 0, "ids cannot be empty");
 
-        try {
-            mCallback.highlightSavedFields(ids);
-        } catch (RemoteException e) {
-            e.rethrowAsRuntimeException();
+        synchronized (mCallback) {
+            checkNotRepliedYetLocked();
+            try {
+                mCallback.highlightSavedFields(ids);
+            } catch (RemoteException e) {
+                e.rethrowAsRuntimeException();
+            } finally {
+                setRepliedLocked();
+            }
         }
     }
 
     /**
      * Notifies the Android System that an
-     * {@link AutoFillService#onSaveRequest(android.app.assist.AssistStructure, Bundle, android.os.CancellationSignal, SaveCallback)}
-     * could not be fulfilled by the service.
+     * {@link AutoFillService#onSaveRequest(android.app.assist.AssistStructure, Bundle,
+     * SaveCallback)} could not be fulfilled by the service.
      *
      * @param message error message to be displayed to the user.
      *
@@ -81,18 +95,53 @@
         if (DEBUG) Log.d(TAG, "onFailure(): message=" + message);
 
         Preconditions.checkArgument(message != null, "message cannot be null");
-        checkNotRepliedYet();
 
-        try {
-            mCallback.showError(message.toString());
-        } catch (RemoteException e) {
-            e.rethrowAsRuntimeException();
+        synchronized (mCallback) {
+            checkNotRepliedYetLocked();
+
+            try {
+                mCallback.showError(message);
+            } catch (RemoteException e) {
+                e.rethrowAsRuntimeException();
+            } finally {
+                setRepliedLocked();
+            }
         }
     }
 
+    /** @hide */
+    @Override
+    public void dump(String prefix, PrintWriter pw) {
+        pw.print(prefix); pw.print("SaveCallback: mReplied="); pw.println(mReplied);
+    }
+
+    /** @hide */
+    @Override
+    public void setFinalizer(Finalizer f) {
+        synchronized (mCallback) {
+            mFinalizer = f;
+        }
+    }
+
+    @Override
+    public String toString() {
+        if (!DEBUG) return super.toString();
+
+        return "SaveCallback: [mReplied= " + mReplied + "]";
+    }
+
     // There can be only one!!
-    private void checkNotRepliedYet() {
+    private void checkNotRepliedYetLocked() {
         Preconditions.checkState(!mReplied, "already replied");
+    }
+
+    private void setRepliedLocked() {
+        if (DEBUG) Log.d(TAG, "setReplied()");
+
         mReplied = true;
+
+        if (mFinalizer != null) {
+            mFinalizer.gone();
+        }
     }
 }
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 417be60..22ad83a 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -925,7 +925,7 @@
     }
 
     /**
-     * Request that the listener be rebound, after a previous call to (@link requestUnbind).
+     * Request that the listener be rebound, after a previous call to {@link #requestUnbind}.
      *
      * <p>This method will fail for listeners that have
      * not been granted the permission by the user.
diff --git a/core/java/android/text/Editable.java b/core/java/android/text/Editable.java
index c0948a6..3396bce 100644
--- a/core/java/android/text/Editable.java
+++ b/core/java/android/text/Editable.java
@@ -94,10 +94,10 @@
     public Editable append(char text);
 
     /**
-     * Convenience for replace(0, length(), "", 0, 0)
-     * @see #replace(int, int, CharSequence, int, int)
+     * Convenience for replace(0, length(), "", 0, 0).
      * Note that this clears the text, not the spans;
      * use {@link #clearSpans} if you need that.
+     * @see #replace(int, int, CharSequence, int, int)
      */
     public void clear();
 
diff --git a/core/java/android/text/FontConfig.java b/core/java/android/text/FontConfig.java
index df694ff..3048a38 100644
--- a/core/java/android/text/FontConfig.java
+++ b/core/java/android/text/FontConfig.java
@@ -164,7 +164,7 @@
      * Class that holds information about a Font.
      */
     public static final class Font implements Parcelable {
-        private final String mFontName;
+        private String mFontName;
         private final int mTtcIndex;
         private final List<Axis> mAxes;
         private final int mWeight;
@@ -203,6 +203,13 @@
         }
 
         /**
+         * @hide
+         */
+        public void setFontName(String fontName) {
+            mFontName = fontName;
+        }
+
+        /**
          * Returns the index to be used to access this font when accessing a TTC file.
          */
         public int getTtcIndex() {
diff --git a/core/java/android/text/ITextClassificationService.aidl b/core/java/android/text/ITextClassificationService.aidl
new file mode 100644
index 0000000..a73dbf0
--- /dev/null
+++ b/core/java/android/text/ITextClassificationService.aidl
@@ -0,0 +1,33 @@
+/*
+ * 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.text;
+
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Interface to the text classification service, which grants access to the text classification
+ * LSTM model file.
+ * {@hide}
+ */
+interface ITextClassificationService {
+
+    /**
+     * Request a file descriptor with read-only access to the LSTM model file.
+     * This file descriptor should be closed after the client is done with it.
+     */
+    ParcelFileDescriptor getModelFileFd();
+}
diff --git a/core/java/android/text/style/ImageSpan.java b/core/java/android/text/style/ImageSpan.java
index 856dd0b..b0bff68 100644
--- a/core/java/android/text/style/ImageSpan.java
+++ b/core/java/android/text/style/ImageSpan.java
@@ -43,7 +43,7 @@
     }
 
     /**
-     * @deprecated Use {@link #ImageSpan(Context, Bitmap, int) instead.
+     * @deprecated Use {@link #ImageSpan(Context, Bitmap, int)} instead.
      */
     @Deprecated
     public ImageSpan(Bitmap b, int verticalAlignment) {
diff --git a/core/java/android/text/style/TtsSpan.java b/core/java/android/text/style/TtsSpan.java
index c5e5df0..d72a48d 100644
--- a/core/java/android/text/style/TtsSpan.java
+++ b/core/java/android/text/style/TtsSpan.java
@@ -798,7 +798,7 @@
         /**
          * Creates a TtsSpan of type {@link #TYPE_DECIMAL} and sets the
          * {@link #ARG_INTEGER_PART} and {@link #ARG_FRACTIONAL_PART} arguments.
-         * @see {@link #setArgumentsFromDouble(double, int, int)
+         * @see #setArgumentsFromDouble(double, int, int)
          */
         public DecimalBuilder(double number,
                               int minimumFractionDigits,
@@ -1082,7 +1082,7 @@
          * Sets the {@link #ARG_UNIT} argument.
          * @param unit The unit of the measure.
          * @return This instance.
-         * @see {@link TtsSpan.ARG_UNIT}
+         * @see TtsSpan.ARG_UNIT
          */
         public MeasureBuilder setUnit(String unit) {
             return setStringArgument(TtsSpan.ARG_UNIT, unit);
@@ -1116,7 +1116,7 @@
          * Sets the {@link #ARG_HOURS} argument.
          * @param hours The value to be set for hours. See {@link #ARG_HOURS}.
          * @return This instance.
-         * @see {@link #ARG_HOURS}
+         * @see #ARG_HOURS
          */
         public TimeBuilder setHours(int hours) {
             return setIntArgument(TtsSpan.ARG_HOURS, hours);
@@ -1127,7 +1127,7 @@
          * @param minutes The value to be set for minutes. See
          *     {@link #ARG_MINUTES}.
          * @return This instance.
-         * @see {@link #ARG_MINUTES}
+         * @see #ARG_MINUTES
          */
         public TimeBuilder setMinutes(int minutes) {
             return setIntArgument(TtsSpan.ARG_MINUTES, minutes);
@@ -1177,7 +1177,7 @@
          * @param weekday The value to be set for weekday. See
          *     {@link #ARG_WEEKDAY}.
          * @return This instance.
-         * @see {@link #ARG_WEEKDAY}
+         * @see #ARG_WEEKDAY
          */
         public DateBuilder setWeekday(int weekday) {
             return setIntArgument(TtsSpan.ARG_WEEKDAY, weekday);
@@ -1187,7 +1187,7 @@
          * Sets the {@link #ARG_DAY} argument.
          * @param day The value to be set for day. See {@link #ARG_DAY}.
          * @return This instance.
-         * @see {@link #ARG_DAY}
+         * @see #ARG_DAY
          */
         public DateBuilder setDay(int day) {
             return setIntArgument(TtsSpan.ARG_DAY, day);
@@ -1197,7 +1197,7 @@
          * Sets the {@link #ARG_MONTH} argument.
          * @param month The value to be set for month. See {@link #ARG_MONTH}.
          * @return This instance.
-         * @see {@link #ARG_MONTH}
+         * @see #ARG_MONTH
          */
         public DateBuilder setMonth(int month) {
             return setIntArgument(TtsSpan.ARG_MONTH, month);
@@ -1207,7 +1207,7 @@
          * Sets the {@link #ARG_YEAR} argument.
          * @param year The value to be set for year. See {@link #ARG_YEAR}.
          * @return This instance.
-         * @see {@link #ARG_YEAR}
+         * @see #ARG_YEAR
          */
         public DateBuilder setYear(int year) {
             return setIntArgument(TtsSpan.ARG_YEAR, year);
diff --git a/core/java/android/util/ByteStringUtils.java b/core/java/android/util/ByteStringUtils.java
index 7103e6d..333208d 100644
--- a/core/java/android/util/ByteStringUtils.java
+++ b/core/java/android/util/ByteStringUtils.java
@@ -33,7 +33,7 @@
    * @param bytes Byte array to encode.
    * @return Hex encoded string representation of bytes.
    */
-  public static String toString(byte[] bytes) {
+  public static String toHexString(byte[] bytes) {
     if (bytes == null || bytes.length == 0 || bytes.length % 2 != 0) {
       return null;
     }
@@ -55,7 +55,7 @@
    * @param str Hex encoded string to decode.
    * @return Decoded byte array representation of str.
    */
-  public static byte[] toByteArray(String str) {
+  public static byte[] fromHexToByteArray(String str) {
     if (str == null || str.length() == 0 || str.length() % 2 != 0) {
       return null;
     }
diff --git a/core/java/android/util/KeyValueListParser.java b/core/java/android/util/KeyValueListParser.java
index e4c025d..be531ff 100644
--- a/core/java/android/util/KeyValueListParser.java
+++ b/core/java/android/util/KeyValueListParser.java
@@ -129,4 +129,22 @@
         }
         return def;
     }
+
+    /**
+     * Get the value for key as a boolean.
+     * @param key The key to lookup.
+     * @param def The value to return if the key was not found.
+     * @return the string value associated with the key.
+     */
+    public boolean getBoolean(String key, boolean def) {
+        String value = mValues.get(key);
+        if (value != null) {
+            try {
+                return Boolean.parseBoolean(value);
+            } catch (NumberFormatException e) {
+                // fallthrough
+            }
+        }
+        return def;
+    }
 }
diff --git a/core/java/android/util/PackageUtils.java b/core/java/android/util/PackageUtils.java
index 3181979..0fe56f6 100644
--- a/core/java/android/util/PackageUtils.java
+++ b/core/java/android/util/PackageUtils.java
@@ -80,6 +80,6 @@
 
         messageDigest.update(data);
 
-        return ByteStringUtils.toString(messageDigest.digest());
+        return ByteStringUtils.toHexString(messageDigest.digest());
     }
 }
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index 37d6757..0a294ab 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -19,7 +19,6 @@
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.os.SystemClock;
-import android.text.format.DateUtils;
 
 import com.android.internal.util.XmlUtils;
 
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 105cc47..3ba55ed 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -163,7 +163,7 @@
 
     /**
      * Display flag: Indicates that the display is private.  Only the application that
-     * owns the display can create windows on it.
+     * owns the display and apps that are already on the display can create windows on it.
      *
      * @see #getFlags
      */
@@ -194,6 +194,19 @@
     public static final int FLAG_ROUND = 1 << 4;
 
     /**
+     * Display flag: Indicates that the display can show its content when non-secure keyguard is
+     * shown.
+     * <p>
+     * This flag identifies secondary displays that won't show keyguard if it can be dismissed
+     * without entering credentials. Display content will be shown even if other displays are
+     * locked.
+     * </p>
+     *
+     * @see #getFlags
+     */
+    public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5;
+
+    /**
      * Display flag: Indicates that the contents of the display should not be scaled
      * to fit the physical screen dimensions.  Used for development only to emulate
      * devices with smaller physicals screens while preserving density.
@@ -777,8 +790,7 @@
     public boolean isHdr() {
         synchronized (this) {
             updateDisplayInfoLocked();
-            int[] types = mDisplayInfo.hdrCapabilities.getSupportedHdrTypes();
-            return types != null && types.length > 0;
+            return mDisplayInfo.isHdr();
         }
     }
 
@@ -788,12 +800,7 @@
     public boolean isWideColorGamut() {
         synchronized (this) {
             updateDisplayInfoLocked();
-            for (int colorMode : mDisplayInfo.supportedColorModes) {
-                if (colorMode == COLOR_MODE_DCI_P3 || colorMode > COLOR_MODE_SRGB) {
-                    return true;
-                }
-            }
-            return false;
+            return mDisplayInfo.isWideColorGamut();
         }
     }
 
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 1aef6ec..f6b94af 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -519,6 +519,20 @@
                 logicalHeight : logicalWidth;
     }
 
+    public boolean isHdr() {
+        int[] types = hdrCapabilities != null ? hdrCapabilities.getSupportedHdrTypes() : null;
+        return types != null && types.length > 0;
+    }
+
+    public boolean isWideColorGamut() {
+        for (int colorMode : supportedColorModes) {
+            if (colorMode == Display.COLOR_MODE_DCI_P3 || colorMode > Display.COLOR_MODE_SRGB) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     /**
      * Returns true if the specified UID has access to this display.
      */
diff --git a/core/java/android/view/FrameMetrics.java b/core/java/android/view/FrameMetrics.java
index 800a63f..92f0e8f 100644
--- a/core/java/android/view/FrameMetrics.java
+++ b/core/java/android/view/FrameMetrics.java
@@ -137,7 +137,7 @@
     /**
      * Identifiers for metrics available for each frame.
      *
-     * {@see {@link #getMetric(int)}}
+     * {@see #getMetric(int)}
      * @hide
      */
     @IntDef({
diff --git a/core/java/android/view/IDockedStackListener.aidl b/core/java/android/view/IDockedStackListener.aidl
index 36a81db..4cf7cf3e 100644
--- a/core/java/android/view/IDockedStackListener.aidl
+++ b/core/java/android/view/IDockedStackListener.aidl
@@ -40,8 +40,11 @@
      *
      * @param minimized Whether the docked stack is currently minimized.
      * @param animDuration The duration of the animation for changing the minimized state.
+     * @param isHomeStackResizable If the home stack is resizable, a portion of the docked stack
+     *        will be shown with the divider
      */
-    void onDockedStackMinimizedChanged(boolean minimized, long animDuration);
+    void onDockedStackMinimizedChanged(boolean minimized, long animDuration,
+            boolean isHomeStackResizable);
 
     /**
      * Called when window manager decides to adjust the divider for IME. Like the minimized state,
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 707300f..10b1e19 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -96,4 +96,9 @@
      * Called when Keyboard Shortcuts are requested for the window.
      */
     void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId);
+
+    /**
+     * Tell the window that it is either gaining or losing pointer capture.
+     */
+    void dispatchPointerCaptureChanged(boolean hasCapture);
 }
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 55f64d9..035d48f 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -237,6 +237,14 @@
     public static final int SOURCE_TRACKBALL = 0x00010000 | SOURCE_CLASS_TRACKBALL;
 
     /**
+     * The input source is a mouse device whose relative motions should be interpreted as
+     * navigation events.
+     *
+     * @see #SOURCE_CLASS_TRACKBALL
+     */
+    public static final int SOURCE_MOUSE_RELATIVE = 0x00020000 | SOURCE_CLASS_TRACKBALL;
+
+    /**
      * The input source is a touch pad or digitizer tablet that is not
      * associated with a display (unlike {@link #SOURCE_TOUCHSCREEN}).
      *
@@ -975,6 +983,7 @@
         appendSourceDescriptionIfApplicable(description, SOURCE_MOUSE, "mouse");
         appendSourceDescriptionIfApplicable(description, SOURCE_STYLUS, "stylus");
         appendSourceDescriptionIfApplicable(description, SOURCE_TRACKBALL, "trackball");
+        appendSourceDescriptionIfApplicable(description, SOURCE_MOUSE_RELATIVE, "mouse_relative");
         appendSourceDescriptionIfApplicable(description, SOURCE_TOUCHPAD, "touchpad");
         appendSourceDescriptionIfApplicable(description, SOURCE_JOYSTICK, "joystick");
         appendSourceDescriptionIfApplicable(description, SOURCE_GAMEPAD, "gamepad");
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
index 88f2d34..02202db 100644
--- a/core/java/android/view/KeyCharacterMap.java
+++ b/core/java/android/view/KeyCharacterMap.java
@@ -675,8 +675,8 @@
      *
      * @return The modifier behavior for this keyboard.
      *
-     * @see {@link #MODIFIER_BEHAVIOR_CHORDED}
-     * @see {@link #MODIFIER_BEHAVIOR_CHORDED_OR_TOGGLED}
+     * @see #MODIFIER_BEHAVIOR_CHORDED
+     * @see #MODIFIER_BEHAVIOR_CHORDED_OR_TOGGLED
      */
     public int getModifierBehavior() {
         switch (getKeyboardType()) {
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index fc66697..ea6e63c 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -139,9 +139,6 @@
                 RenderNode.class.getClassLoader(), nGetNativeFinalizer(), 1024);
     }
 
-    // Note: written by native when display lists are detached
-    private boolean mValid;
-
     // Do not access directly unless you are ThreadedRenderer
     final long mNativeRenderNode;
     private final View mOwningView;
@@ -233,7 +230,6 @@
         long displayList = canvas.finishRecording();
         nSetDisplayList(mNativeRenderNode, displayList);
         canvas.recycle();
-        mValid = true;
     }
 
     /**
@@ -242,10 +238,7 @@
      * obsolete resources after related resources are gone.
      */
     public void discardDisplayList() {
-        if (!mValid) return;
-
         nSetDisplayList(mNativeRenderNode, 0);
-        mValid = false;
     }
 
     /**
@@ -254,10 +247,12 @@
      *
      * @return boolean true if the display list is able to be replayed, false otherwise.
      */
-    public boolean isValid() { return mValid; }
+    public boolean isValid() {
+        return nIsValid(mNativeRenderNode);
+    }
 
     long getNativeDisplayList() {
-        if (!mValid) {
+        if (!isValid()) {
             throw new IllegalStateException("The display list is not valid.");
         }
         return mNativeRenderNode;
@@ -827,8 +822,7 @@
     // Regular JNI methods
     ///////////////////////////////////////////////////////////////////////////
 
-    // Intentionally not static because it acquires a reference to 'this'
-    private native long nCreate(String name);
+    private static native long nCreate(String name);
 
     private static native long nGetNativeFinalizer();
     private static native void nOutput(long renderNode);
@@ -853,6 +847,9 @@
     // @CriticalNative methods
     ///////////////////////////////////////////////////////////////////////////
 
+    @CriticalNative
+    private static native boolean nIsValid(long renderNode);
+
     // Matrix
 
     @CriticalNative
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index a12600a..5bb577f 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -34,7 +34,7 @@
     private static final String TAG = "SurfaceControl";
 
     private static native long nativeCreate(SurfaceSession session, String name,
-            int w, int h, int format, int flags)
+            int w, int h, int format, int flags, long parentObject)
             throws OutOfResourcesException;
     private static native void nativeRelease(long nativeObject);
     private static native void nativeDestroy(long nativeObject);
@@ -287,6 +287,12 @@
     public SurfaceControl(SurfaceSession session,
             String name, int w, int h, int format, int flags)
                     throws OutOfResourcesException {
+        this(session, name, w, h, format, flags, null);
+    }
+
+    public SurfaceControl(SurfaceSession session,
+            String name, int w, int h, int format, int flags, SurfaceControl parent)
+                    throws OutOfResourcesException {
         if (session == null) {
             throw new IllegalArgumentException("session must not be null");
         }
@@ -304,7 +310,7 @@
         }
 
         mName = name;
-        mNativeObject = nativeCreate(session, name, w, h, format, flags);
+        mNativeObject = nativeCreate(session, name, w, h, format, flags, parent != null ? parent.mNativeObject : 0);
         if (mNativeObject == 0) {
             throw new OutOfResourcesException(
                     "Couldn't allocate SurfaceControl native object");
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index f3ebcb4..4ceb236 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -496,15 +496,6 @@
 
     private static void destroyResources(View view) {
         view.destroyHardwareResources();
-
-        if (view instanceof ViewGroup) {
-            ViewGroup group = (ViewGroup) view;
-
-            int count = group.getChildCount();
-            for (int i = 0; i < count; i++) {
-                destroyResources(group.getChildAt(i));
-            }
-        }
     }
 
     /**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 15b62a2..597c051 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -104,6 +104,7 @@
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Transformation;
+import android.view.autofill.AutoFillManager;
 import android.view.autofill.AutoFillType;
 import android.view.autofill.AutoFillValue;
 import android.view.autofill.VirtualViewDelegate;
@@ -1765,12 +1766,6 @@
      */
     int mAccessibilityViewId = NO_ID;
 
-    /**
-     * The stable ID of this view for auto-fill purposes.
-     */
-    private int mAutoFillId = NO_ID;
-
-
     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
 
     SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
@@ -3704,6 +3699,8 @@
         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
 
         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
+
+        OnCapturedPointerListener mOnCapturedPointerListener;
     }
 
     ListenerInfo mListenerInfo;
@@ -4043,9 +4040,9 @@
      * input fields and tags (like {@code id}).
      * </ul>
      */
-    // TODO(b/33197203) (b/34078930): improve documentation: mention all cases, show examples, etc.
-    // In particular, be more specific about webview restrictions
-    public static final int AUTO_FILL_FLAG_TYPE_FILL = 0x1;
+    // TODO(b/33197203): cannot conflict with flags defined on AutoFillManager until they're removed
+    // (when save is refactored).
+    public static final int AUTO_FILL_FLAG_TYPE_FILL = 0x10000000;
 
     /**
      * Set when the user explicitly asked a {@link android.service.autofill.AutoFillService} to save
@@ -4055,7 +4052,9 @@
      * (Personally Identifiable Information). For example, the text of password fields should be
      * included since that's what's typically saved.
      */
-    public static final int AUTO_FILL_FLAG_TYPE_SAVE = 0x2;
+    // TODO(b/33197203): cannot conflict with flags defined on AutoFillManager until they're removed
+    // (when save is refactored).
+    public static final int AUTO_FILL_FLAG_TYPE_SAVE = 0x20000000;
 
     /**
      * Set to true when drawing cache is enabled and cannot be created.
@@ -6391,6 +6390,14 @@
      * @see ViewGroup#getTouchscreenBlocksFocus()
      */
     public boolean hasFocusable() {
+        return hasFocusable(true);
+    }
+
+    /**
+     * @hide pending determination of whether this should be public or not.
+     * Currently used for compatibility with old focusability expectations in ListView.
+     */
+    public boolean hasFocusable(boolean allowAutoFocus) {
         if (!isFocusableInTouchMode()) {
             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
                 final ViewGroup g = (ViewGroup) p;
@@ -6399,7 +6406,10 @@
                 }
             }
         }
-        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
+        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
+            return false;
+        }
+        return allowAutoFocus ? getFocusable() != NOT_FOCUSABLE : getFocusable() == FOCUSABLE;
     }
 
     /**
@@ -6435,16 +6445,23 @@
             if (isPressed()) {
                 setPressed(false);
             }
-            if (imm != null && mAttachInfo != null
-                    && mAttachInfo.mHasWindowFocus) {
+            if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
                 imm.focusOut(this);
             }
             onFocusLost();
-        } else if (imm != null && mAttachInfo != null
-                && mAttachInfo.mHasWindowFocus) {
+        } else if (imm != null && mAttachInfo != null && mAttachInfo.mHasWindowFocus) {
             imm.focusIn(this);
         }
 
+        if (isAutoFillable()) {
+            AutoFillManager afm = getAutoFillManager();
+            if (afm != null) {
+                afm.updateAutoFillInput(this, gainFocus
+                        ? AutoFillManager.FLAG_UPDATE_UI_SHOW
+                        : AutoFillManager.FLAG_UPDATE_UI_HIDE);
+            }
+        }
+
         invalidate(true);
         ListenerInfo li = mListenerInfo;
         if (li != null && li.mOnFocusChangeListener != null) {
@@ -6938,8 +6955,7 @@
         if (forAutoFill) {
             // The auto-fill id needs to be unique, but its value doesn't matter, so it's better to
             // reuse the accessibility id to save space.
-            mAutoFillId = getAccessibilityViewId();
-            structure.setAutoFillId(mAutoFillId);
+            structure.setAutoFillId(getAccessibilityViewId());
             structure.setAutoFillType(getAutoFillType());
         }
 
@@ -7081,6 +7097,15 @@
         return null;
     }
 
+    @Nullable
+    private AutoFillManager getAutoFillManager() {
+        return mContext.getSystemService(AutoFillManager.class);
+    }
+
+    private boolean isAutoFillable() {
+        return getAutoFillType() != null && !isAutoFillBlocked();
+    }
+
     private void populateVirtualStructure(ViewStructure structure,
             AccessibilityNodeProvider provider, AccessibilityNodeInfo info, int flags) {
         // NOTE: currently flags are only used for AutoFill; if they're used for Assist as well,
@@ -7566,20 +7591,6 @@
     }
 
     /**
-     * Gets the unique identifier of this view for auto-fill purposes.
-     *
-     * <p>It's only set after {@link #onProvideAutoFillStructure(ViewStructure, int)} is called.
-     *
-     * @return The view autofill id or {@link #NO_ID} if
-     * {@link #onProvideAutoFillStructure(ViewStructure, int)}  was not called yet.
-     *
-     * @hide
-     */
-    public int getAutoFillViewId() {
-        return mAutoFillId;
-    }
-
-    /**
      * Gets the unique identifier of the window in which this View reseides.
      *
      * @return The window accessibility id.
@@ -10661,6 +10672,25 @@
     }
 
     /**
+     * Pass a captured pointer event down to the focused view.
+     *
+     * @param event The motion event to be dispatched.
+     * @return True if the event was handled by the view, false otherwise.
+     */
+    public boolean dispatchCapturedPointerEvent(MotionEvent event) {
+        if (!hasPointerCapture()) {
+            return false;
+        }
+        //noinspection SimplifiableIfStatement
+        ListenerInfo li = mListenerInfo;
+        if (li != null && li.mOnCapturedPointerListener != null
+                && li.mOnCapturedPointerListener.onCapturedPointer(this, event)) {
+            return true;
+        }
+        return onCapturedPointerEvent(event);
+    }
+
+    /**
      * Dispatch a generic motion event.
      * <p>
      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
@@ -13562,7 +13592,7 @@
      * Any previously attached StateListAnimator will be detached.
      *
      * @param stateListAnimator The StateListAnimator to update the view
-     * @see {@link android.animation.StateListAnimator}
+     * @see android.animation.StateListAnimator
      */
     public void setStateListAnimator(StateListAnimator stateListAnimator) {
         if (mStateListAnimator == stateListAnimator) {
@@ -16613,11 +16643,12 @@
      */
     @CallSuper
     protected void destroyHardwareResources() {
-        // Although the Layer will be destroyed by RenderNode, we want to release
-        // the staging display list, which is also a signal to RenderNode that it's
-        // safe to free its copy of the display list as it knows that we will
-        // push an updated DisplayList if we try to draw again
-        resetDisplayList();
+        if (mOverlay != null) {
+            mOverlay.getOverlayView().destroyHardwareResources();
+        }
+        if (mGhostView != null) {
+            mGhostView.destroyHardwareResources();
+        }
     }
 
     /**
@@ -16788,11 +16819,8 @@
     }
 
     private void resetDisplayList() {
-        if (mRenderNode.isValid()) {
-            mRenderNode.discardDisplayList();
-        }
-
-        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
+        mRenderNode.discardDisplayList();
+        if (mBackgroundRenderNode != null) {
             mBackgroundRenderNode.discardDisplayList();
         }
     }
@@ -22688,7 +22716,110 @@
         return mPointerIcon;
     }
 
-    //
+    /**
+     * Checks pointer capture status.
+     *
+     * @return true if the view has pointer capture.
+     * @see #requestPointerCapture()
+     * @see #hasPointerCapture()
+     */
+    public boolean hasPointerCapture() {
+        final ViewRootImpl viewRootImpl = getViewRootImpl();
+        if (viewRootImpl == null) {
+            return false;
+        }
+        return viewRootImpl.hasPointerCapture();
+    }
+
+    /**
+     * Requests pointer capture mode.
+     * <p>
+     * When the window has pointer capture, the mouse pointer icon will disappear and will not
+     * change its position. Further mouse will be dispatched with the source
+     * {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be available
+     * through {@link MotionEvent#getX} and {@link MotionEvent#getY}. Non-mouse events
+     * (touchscreens, or stylus) will not be affected.
+     * <p>
+     * If the window already has pointer capture, this call does nothing.
+     * <p>
+     * The capture may be released through {@link #releasePointerCapture()}, or will be lost
+     * automatically when the window loses focus.
+     *
+     * @see #releasePointerCapture()
+     * @see #hasPointerCapture()
+     */
+    public void requestPointerCapture() {
+        final ViewRootImpl viewRootImpl = getViewRootImpl();
+        if (viewRootImpl != null) {
+            viewRootImpl.requestPointerCapture(true);
+        }
+    }
+
+
+    /**
+     * Releases the pointer capture.
+     * <p>
+     * If the window does not have pointer capture, this call will do nothing.
+     * @see #requestPointerCapture()
+     * @see #hasPointerCapture()
+     */
+    public void releasePointerCapture() {
+        final ViewRootImpl viewRootImpl = getViewRootImpl();
+        if (viewRootImpl != null) {
+            viewRootImpl.requestPointerCapture(false);
+        }
+    }
+
+    /**
+     * Called when the window has just acquired or lost pointer capture.
+     *
+     * @param hasCapture True if the view now has pointerCapture, false otherwise.
+     */
+    @CallSuper
+    public void onPointerCaptureChange(boolean hasCapture) {
+    }
+
+    /**
+     * @see #onPointerCaptureChange
+     */
+    public void dispatchPointerCaptureChanged(boolean hasCapture) {
+        onPointerCaptureChange(hasCapture);
+    }
+
+    /**
+     * Implement this method to handle captured pointer events
+     *
+     * @param event The captured pointer event.
+     * @return True if the event was handled, false otherwise.
+     * @see #requestPointerCapture()
+     */
+    public boolean onCapturedPointerEvent(MotionEvent event) {
+        return false;
+    }
+
+    /**
+     * Interface definition for a callback to be invoked when a captured pointer event
+     * is being dispatched this view. The callback will be invoked before the event is
+     * given to the view.
+     */
+    public interface OnCapturedPointerListener {
+        /**
+         * Called when a captured pointer event is dispatched to a view.
+         * @param view The view this event has been dispatched to.
+         * @param event The captured event.
+         * @return True if the listener has consumed the event, false otherwise.
+         */
+        boolean onCapturedPointer(View view, MotionEvent event);
+    }
+
+    /**
+     * Set a listener to receive callbacks when the pointer capture state of a view changes.
+     * @param l  The {@link OnCapturedPointerListener} to receive callbacks.
+     */
+    public void setOnCapturedPointerListener(OnCapturedPointerListener l) {
+        getListenerInfo().mOnCapturedPointerListener = l;
+    }
+
     // Properties
     //
     /**
@@ -24637,12 +24768,9 @@
     }
 
     /**
-     * To be removed once the support library has stopped using it.
-     *
-     * @deprecated use {@link #setTooltipText} instead
+     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
      */
-    @Deprecated
-    public final void setTooltip(@Nullable CharSequence tooltipText) {
+    public void setTooltip(@Nullable CharSequence tooltipText) {
         setTooltipText(tooltipText);
     }
 
@@ -24657,13 +24785,10 @@
     }
 
     /**
-     * To be removed once the support library has stopped using it.
-     *
-     * @deprecated use {@link #getTooltipText} instead
+     * @hide Binary compatibility stub. To be removed when we finalize O APIs.
      */
-    @Deprecated
     @Nullable
-    public final CharSequence getTooltip() {
+    public CharSequence getTooltip() {
         return getTooltipText();
     }
 
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index ba73c5f..b135bef 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1105,13 +1105,15 @@
         return null;
     }
 
+    /** @hide Overriding hidden method */
     @Override
-    public boolean hasFocusable() {
+    public boolean hasFocusable(boolean allowAutoFocus) {
         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
             return false;
         }
 
-        if (isFocusable()) {
+        // TODO This should probably be super.hasFocusable, but that would change behavior
+        if (allowAutoFocus ? getFocusable() != NOT_FOCUSABLE : getFocusable() == FOCUSABLE) {
             return true;
         }
 
@@ -1122,7 +1124,7 @@
 
             for (int i = 0; i < count; i++) {
                 final View child = children[i];
-                if (child.hasFocusable()) {
+                if (child.hasFocusable(allowAutoFocus)) {
                     return true;
                 }
             }
@@ -1756,6 +1758,34 @@
     }
 
     @Override
+    public boolean dispatchCapturedPointerEvent(MotionEvent event) {
+        if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
+                == (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
+            if (super.dispatchCapturedPointerEvent(event)) {
+                return true;
+            }
+        } else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
+                == PFLAG_HAS_BOUNDS) {
+            if (mFocused.dispatchCapturedPointerEvent(event)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public void dispatchPointerCaptureChanged(boolean hasCapture) {
+        exitHoverTargets();
+
+        super.dispatchPointerCaptureChanged(hasCapture);
+        final int count = mChildrenCount;
+        final View[] children = mChildren;
+        for (int i = 0; i < count; i++) {
+            children[i].dispatchPointerCaptureChanged(hasCapture);
+        }
+    }
+
+    @Override
     public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
         final float x = event.getX(pointerIndex);
         final float y = event.getY(pointerIndex);
@@ -4597,6 +4627,16 @@
         clearCachedLayoutMode();
     }
 
+    /** @hide */
+    @Override
+    protected void destroyHardwareResources() {
+        super.destroyHardwareResources();
+        int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            getChildAt(i).destroyHardwareResources();
+        }
+    }
+
     /**
      * Adds a view during layout. This is useful if in your onLayout() method,
      * you need to add more views (as does the list view for example).
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 6987e09..c9b9d5f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -192,8 +192,8 @@
     View mAccessibilityFocusedHost;
     AccessibilityNodeInfo mAccessibilityFocusedVirtualView;
 
-    // The view which captures mouse input, or null when no one is capturing.
-    View mCapturingView;
+    // True if the window currently has pointer capture enabled.
+    boolean mPointerCapture;
 
     int mViewVisibility;
     boolean mAppVisible = true;
@@ -3200,6 +3200,27 @@
         }
     }
 
+    boolean hasPointerCapture() {
+        return mPointerCapture;
+    }
+
+    void requestPointerCapture(boolean enabled) {
+        if (mPointerCapture == enabled) {
+            return;
+        }
+        InputManager.getInstance().requestPointerCapture(mAttachInfo.mWindowToken, enabled);
+    }
+
+    private void handlePointerCaptureChanged(boolean hasCapture) {
+        if (mPointerCapture == hasCapture) {
+            return;
+        }
+        mPointerCapture = hasCapture;
+        if (mView != null) {
+            mView.dispatchPointerCaptureChanged(hasCapture);
+        }
+    }
+
     @Override
     public void requestChildFocus(View child, View focused) {
         if (DEBUG_INPUT_RESIZE) {
@@ -3393,6 +3414,7 @@
     private final static int MSG_DISPATCH_WINDOW_SHOWN = 25;
     private final static int MSG_REQUEST_KEYBOARD_SHORTCUTS = 26;
     private final static int MSG_UPDATE_POINTER_ICON = 27;
+    private final static int MSG_POINTER_CAPTURE_CHANGED = 28;
 
     final class ViewRootHandler extends Handler {
         @Override
@@ -3442,6 +3464,8 @@
                     return "MSG_DISPATCH_WINDOW_SHOWN";
                 case MSG_UPDATE_POINTER_ICON:
                     return "MSG_UPDATE_POINTER_ICON";
+                case MSG_POINTER_CAPTURE_CHANGED:
+                    return "MSG_POINTER_CAPTURE_CHANGED";
             }
             return super.getMessageName(message);
         }
@@ -3613,6 +3637,10 @@
                                 .softInputMode &=
                                     ~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
                         mHasHadWindowFocus = true;
+                    } else {
+                        if (mPointerCapture) {
+                            handlePointerCaptureChanged(false);
+                        }
                     }
                 }
             } break;
@@ -3691,6 +3719,10 @@
                 MotionEvent event = (MotionEvent) msg.obj;
                 resetPointerIcon(event);
             } break;
+            case MSG_POINTER_CAPTURE_CHANGED: {
+                final boolean hasCapture = msg.arg1 != 0;
+                handlePointerCaptureChanged(hasCapture);
+            } break;
             }
         }
     }
@@ -4472,11 +4504,8 @@
             final MotionEvent event = (MotionEvent)q.mEvent;
 
             mAttachInfo.mUnbufferedDispatchRequested = false;
-            final View eventTarget =
-                    (event.isFromSource(InputDevice.SOURCE_MOUSE) && mCapturingView != null) ?
-                            mCapturingView : mView;
             mAttachInfo.mHandlingPointerEvent = true;
-            boolean handled = eventTarget.dispatchPointerEvent(event);
+            boolean handled = mView.dispatchPointerEvent(event);
             maybeUpdatePointerIcon(event);
             maybeUpdateTooltip(event);
             mAttachInfo.mHandlingPointerEvent = false;
@@ -4510,6 +4539,12 @@
         private int processTrackballEvent(QueuedInputEvent q) {
             final MotionEvent event = (MotionEvent)q.mEvent;
 
+            if (event.isFromSource(InputDevice.SOURCE_MOUSE_RELATIVE)) {
+                if (!hasPointerCapture() || mView.dispatchCapturedPointerEvent(event)) {
+                    return FINISH_HANDLED;
+                }
+            }
+
             if (mView.dispatchTrackballEvent(event)) {
                 return FINISH_HANDLED;
             }
@@ -6700,6 +6735,14 @@
                 MSG_REQUEST_KEYBOARD_SHORTCUTS, deviceId, 0, receiver).sendToTarget();
     }
 
+    public void dispatchPointerCaptureChanged(boolean on) {
+        final int what = MSG_POINTER_CAPTURE_CHANGED;
+        mHandler.removeMessages(what);
+        Message msg = mHandler.obtainMessage(what);
+        msg.arg1 = on ? 1 : 0;
+        mHandler.sendMessage(msg);
+    }
+
     /**
      * Post a callback to send a
      * {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event.
@@ -7280,6 +7323,15 @@
                 viewAncestor.dispatchRequestKeyboardShortcuts(receiver, deviceId);
             }
         }
+
+        @Override
+        public void dispatchPointerCaptureChanged(boolean hasCapture) {
+            final ViewRootImpl viewAncestor = mViewAncestor.get();
+            if (viewAncestor != null) {
+                viewAncestor.dispatchPointerCaptureChanged(hasCapture);
+            }
+        }
+
     }
 
     public static final class CalledFromWrongThreadException extends AndroidRuntimeException {
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index e2bdd97..0053caa 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -574,6 +574,13 @@
          */
         default public void onProvideKeyboardShortcuts(
                 List<KeyboardShortcutGroup> data, @Nullable Menu menu, int deviceId) { };
+
+        /**
+         * Called when pointer capture is enabled or disabled for the current window.
+         *
+         * @param hasCapture True if the window has pointer capture.
+         */
+        default public void onPointerCaptureChanged(boolean hasCapture) { };
     }
 
     /** @hide */
@@ -1917,7 +1924,7 @@
     public Transition getEnterTransition() { return null; }
 
     /**
-     * Returns he Transition that will be used to move Views out of the scene when the Window is
+     * Returns the Transition that will be used to move Views out of the scene when the Window is
      * preparing to close, for example after a call to
      * {@link android.app.Activity#finishAfterTransition()}. The exiting
      * Views will be those that are regular Views or ViewGroups that have
diff --git a/core/java/android/view/WindowCallbackWrapper.java b/core/java/android/view/WindowCallbackWrapper.java
index 8f2d2e1..02c8945 100644
--- a/core/java/android/view/WindowCallbackWrapper.java
+++ b/core/java/android/view/WindowCallbackWrapper.java
@@ -158,5 +158,10 @@
             List<KeyboardShortcutGroup> data, Menu menu, int deviceId) {
         mWrapped.onProvideKeyboardShortcuts(data, menu, deviceId);
     }
+
+    @Override
+    public void onPointerCaptureChanged(boolean hasCapture) {
+        mWrapped.onPointerCaptureChanged(hasCapture);
+    }
 }
 
diff --git a/core/java/android/view/animation/LayoutAnimationController.java b/core/java/android/view/animation/LayoutAnimationController.java
index df2f18c..7fa49c1 100644
--- a/core/java/android/view/animation/LayoutAnimationController.java
+++ b/core/java/android/view/animation/LayoutAnimationController.java
@@ -150,7 +150,7 @@
      * Returns the order used to compute the delay of each child's animation.
      *
      * @return one of {@link #ORDER_NORMAL}, {@link #ORDER_REVERSE} or
-     *         {@link #ORDER_RANDOM)
+     *         {@link #ORDER_RANDOM}
      *
      * @attr ref android.R.styleable#LayoutAnimation_animationOrder
      */
diff --git a/core/java/android/view/autofill/AutoFillManager.java b/core/java/android/view/autofill/AutoFillManager.java
index cd9842f..cf56e0e 100644
--- a/core/java/android/view/autofill/AutoFillManager.java
+++ b/core/java/android/view/autofill/AutoFillManager.java
@@ -36,12 +36,16 @@
     /**
      * Flag used to show the auto-fill UI affordance for a view.
      */
-    public static final int FLAG_UPDATE_UI_SHOW = 1 << 0;
+    // TODO(b/33197203): cannot conflict with flags defined on View until they're removed (when
+    // save is refactored).
+    public static final int FLAG_UPDATE_UI_SHOW = 0x1;
 
     /**
      * Flag used to hide the auto-fill UI affordance for a view.
      */
-    public static final int FLAG_UPDATE_UI_HIDE = 1 << 1;
+    // TODO(b/33197203): cannot conflict with flags defined on View until they're removed (when
+    // save is refactored).
+    public static final int FLAG_UPDATE_UI_HIDE = 0x2;
 
     private final IAutoFillManagerService mService;
 
@@ -64,11 +68,10 @@
      * {@link #FLAG_UPDATE_UI_HIDE}.
      */
     public void updateAutoFillInput(View view, int flags) {
-        if (DEBUG) {
-            Log.v(TAG, "updateAutoFillInput(" + view.getAutoFillViewId() + "): flags=" + flags);
-        }
+        final Rect bounds = new Rect();
+        view.getBoundsOnScreen(bounds);
 
-        updateAutoFillInput(view, false, View.NO_ID, null, flags);
+        requestAutoFill(new AutoFillId(view.getAccessibilityViewId()), bounds, flags);
     }
 
     /**
@@ -79,56 +82,22 @@
      *
      * @param parent parent view.
      * @param childId id identifying the virtual child inside the parent view.
-     * @param boundaries boundaries of the child (inside the parent; could be {@code null} when
+     * @param bounds absolute boundaries of the child in the window (could be {@code null} when
      * flag is {@link #FLAG_UPDATE_UI_HIDE}.
      * @param flags either {@link #FLAG_UPDATE_UI_SHOW} or
      * {@link #FLAG_UPDATE_UI_HIDE}.
      */
-    public void updateAutoFillInput(View parent, int childId, @Nullable Rect boundaries,
+    public void updateAutoFillInput(View parent, int childId, @Nullable Rect bounds,
             int flags) {
+        requestAutoFill(new AutoFillId(parent.getAccessibilityViewId(), childId), bounds, flags);
+    }
+
+    private void requestAutoFill(AutoFillId id, Rect bounds, int flags) {
         if (DEBUG) {
-            Log.v(TAG, "updateAutoFillInput(" + parent.getAutoFillViewId() + ", " + childId
-                    + "): boundaries=" + boundaries + ", flags=" + flags);
+            Log.v(TAG, "requestAutoFill(): id=" + id + ", bounds=" + bounds + ", flags=" + flags);
         }
-        updateAutoFillInput(parent, true, childId, boundaries, flags);
-    }
-
-    private void updateAutoFillInput(View view, boolean virtual, int childId, Rect boundaries,
-            int flags) {
-        if ((flags & FLAG_UPDATE_UI_SHOW) != 0) {
-            final int viewId = view.getAutoFillViewId();
-            final AutoFillId id = virtual
-                    ? new AutoFillId(viewId, childId)
-                    : new AutoFillId(viewId);
-            showAutoFillInput(id, boundaries);
-            return;
-        }
-        // TODO(b/33197203): handle FLAG_UPDATE_UI_HIDE
-    }
-
-    private void showAutoFillInput(AutoFillId id, Rect boundaries) {
-        final int autoFillViewId = id.getViewId();
-        /*
-         * TODO(b/33197203): currently SHOW_AUTO_FILL_BAR is only set once per activity (i.e, when
-         * the view does not have an auto-fill id), but it should be called again for views that
-         * were not part of the initial auto-fill dataset returned by the service. For example:
-         *
-         * 1.Activity has 4 fields, `first_name`, `last_name`, and `address`.
-         * 2.User taps `first_name`.
-         * 3.Service returns a dataset with ids for `first_name` and `last_name`.
-         * 4.When user taps `first_name` (again) or `last_name`, flag should not have
-         *   SHOW_AUTO_FILL_BAR set, but when user taps `address`, it should (since that field was
-         *   not part of the initial dataset).
-         *
-         * Similarly, once the activity is auto-filled, the flag logic should be reset (so if the
-         * user taps the view again, a new auto-fill request is made)
-         */
-        if (autoFillViewId != View.NO_ID) {
-            return;
-        }
-
         try {
-            mService.showAutoFillInput(id, boundaries);
+            mService.requestAutoFill(id, bounds, flags);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/view/autofill/AutoFillSession.java b/core/java/android/view/autofill/AutoFillSession.java
new file mode 100644
index 0000000..eec7a82
--- /dev/null
+++ b/core/java/android/view/autofill/AutoFillSession.java
@@ -0,0 +1,118 @@
+/*
+ * 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.view.autofill;
+
+import static android.view.autofill.Helper.DEBUG;
+
+import android.app.Activity;
+import android.os.RemoteException;
+import android.service.autofill.IAutoFillAppCallback;
+import android.util.Log;
+import android.view.View;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * An auto-fill session associated with an activity.
+ *
+ * @hide
+ */
+public final class AutoFillSession {
+
+    private static final String TAG = "AutoFillSession";
+
+    private final IAutoFillAppCallback mCallback = new IAutoFillAppCallback.Stub() {
+        @Override
+        public void autoFill(Dataset dataset) throws RemoteException {
+            final Activity activity = mActivity.get();
+            if (activity == null) {
+                if (DEBUG) Log.d(TAG, "autoFill(): activity already GCed");
+                return;
+            }
+            // TODO(b/33197203): must keep the dataset so subsequent calls pass the same
+            // dataset.extras to service
+            activity.runOnUiThread(() -> {
+                final View root = activity.getWindow().getDecorView().getRootView();
+                for (DatasetField field : dataset.getFields()) {
+                    final AutoFillId id = field.getId();
+                    if (id == null) {
+                        Log.w(TAG, "autoFill(): null id on " + field);
+                        continue;
+                    }
+                    final int viewId = id.getViewId();
+                    final View view = root.findViewByAccessibilityIdTraversal(viewId);
+                    if (view == null) {
+                        Log.w(TAG, "autoFill(): no View with id " + viewId);
+                        continue;
+                    }
+
+                    // TODO(b/33197203): handle protected value (like credit card)
+                    if (id.isVirtual()) {
+                        // Delegate virtual fields.
+                        setAutoFillDelegateCallback();
+                        final VirtualViewDelegate delegate = view
+                                .getAutoFillVirtualViewDelegate(
+                                        mAutoFillDelegateCallback);
+                        if (delegate == null) {
+                            Log.w(TAG, "autoFill(): cannot fill virtual " + id
+                                    + "; no VirtualViewDelegate for view "
+                                    + view.getClass());
+                            continue;
+                        }
+                        if (DEBUG) {
+                            Log.d(TAG, "autoFill(): delegating " + id
+                                    + " to VirtualViewDelegate  " + delegate);
+                        }
+                        delegate.autoFill(id.getVirtualChildId(), field.getValue());
+                    } else {
+                        // Handle non-virtual fields itself.
+                        view.autoFill(field.getValue());
+                    }
+                }
+            });
+        }
+    };
+
+    private final WeakReference<Activity> mActivity;
+
+    @GuardedBy("this")
+    private VirtualViewDelegate.Callback mAutoFillDelegateCallback;
+
+    public AutoFillSession(Activity activity) {
+        mActivity = new WeakReference<>(activity);
+    }
+
+    public IAutoFillAppCallback getCallback() {
+        return mCallback;
+    }
+
+    /**
+     * Lazily sets the {@link #mAutoFillDelegateCallback}.
+     */
+    private void setAutoFillDelegateCallback() {
+        synchronized (this) {
+            if (mAutoFillDelegateCallback == null) {
+                mAutoFillDelegateCallback = new VirtualViewDelegate.Callback() {
+                    // TODO(b/33197203): implement
+                };
+            }
+        }
+    }
+
+}
diff --git a/core/java/android/view/autofill/Dataset.java b/core/java/android/view/autofill/Dataset.java
index a73eb774..18a08f9 100644
--- a/core/java/android/view/autofill/Dataset.java
+++ b/core/java/android/view/autofill/Dataset.java
@@ -19,12 +19,13 @@
 import static android.view.autofill.Helper.DEBUG;
 import static android.view.autofill.Helper.append;
 
+import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.assist.AssistStructure.ViewNode;
+import android.hardware.fingerprint.FingerprintManager.CryptoObject;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.service.autofill.AutoFillService;
 
 import com.android.internal.util.Preconditions;
 
@@ -50,12 +51,20 @@
     private final CharSequence mName;
     private final ArrayList<DatasetField> mFields;
     private final Bundle mExtras;
+    private final int mFlags;
+    private final boolean mRequiresAuth;
+    private final boolean mHasCryptoObject;
+    private final long mCryptoOpId;
 
     private Dataset(Dataset.Builder builder) {
         mName = builder.mName;
         // TODO(b/33197203): make an immutable copy of mFields?
         mFields = builder.mFields;
         mExtras = builder.mExtras;
+        mFlags = builder.mFlags;
+        mRequiresAuth = builder.mRequiresAuth;
+        mHasCryptoObject = builder.mHasCryptoObject;
+        mCryptoOpId = builder.mCryptoOpId;
     }
 
     /** @hide */
@@ -73,13 +82,41 @@
         return mExtras;
     }
 
+    /** @hide */
+    public int getFlags() {
+        return mFlags;
+    }
+
+    /** @hide */
+    public boolean isAuthRequired() {
+        return mRequiresAuth;
+    }
+
+    /** @hide */
+    public boolean isEmpty() {
+        return mFields.isEmpty();
+    }
+
+    /** @hide */
+    public boolean hasCryptoObject() {
+        return mHasCryptoObject;
+    }
+
+    /** @hide */
+    public long getCryptoObjectOpId() {
+        return mCryptoOpId;
+    }
+
     @Override
     public String toString() {
         if (!DEBUG) return super.toString();
 
         final StringBuilder builder = new StringBuilder("Dataset [name=").append(mName)
                 .append(", fields=").append(mFields).append(", extras=");
-        append(builder, mExtras);
+        append(builder, mExtras)
+            .append(", flags=").append(mFlags)
+            .append(", requiresAuth: ").append(mRequiresAuth)
+            .append(", hasCrypto: ").append(mHasCryptoObject);
         return builder.append(']').toString();
     }
 
@@ -90,6 +127,10 @@
         private CharSequence mName;
         private final ArrayList<DatasetField> mFields = new ArrayList<>();
         private Bundle mExtras;
+        private int mFlags;
+        private boolean mRequiresAuth;
+        private boolean mHasCryptoObject;
+        private long mCryptoOpId;
 
         /**
          * Creates a new builder.
@@ -103,6 +144,125 @@
         }
 
         /**
+         * Requires dataset authentication through the {@link
+         * android.service.autofill.AutoFillService} before auto-filling the activity with this
+         * dataset.
+         *
+         * <p>This method is typically called when the device (or the service) does not support
+         * fingerprint authentication (and hence it cannot use {@link
+         * #requiresFingerprintAuthentication(CryptoObject, Bundle, int)}) or when the service needs
+         * to use a custom authentication UI for the dataset. For example, when a dataset contains
+         * credit card information (such as number, expiration date, and verification code), the
+         * service displays an authentication dialog asking for the verification code to unlock the
+         * rest of the data).
+         *
+         * <p>Since the dataset is "locked" until the user authenticates it, typically this dataset
+         * name is masked (for example, "VISA....1234").
+         *
+         * <p>When the user selects this dataset, the Android System calls {@link
+         * android.service.autofill.AutoFillService#onDatasetAuthenticationRequest(Bundle, int)}
+         * passing {@link android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_REQUESTED} in
+         * the flags and the same {@code extras} passed to this method. The service can then
+         * displays its custom authentication UI, and then call the proper method on {@link
+         * android.service.autofill.FillCallback} depending on the authentication result and whether
+         * this dataset already contains the fields needed to auto-fill the activity:
+         *
+         * <ul>
+         *   <li>If authentication failed, call
+         *   {@link android.service.autofill.FillCallback#onDatasetAuthentication(Dataset,
+         *       int)} passing {@link
+         *       android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_ERROR} in the flags.
+         *   <li>If authentication succeeded and this datast is empty (no fields), call {@link
+         *       android.service.autofill.FillCallback#onSuccess(FillResponse)} with a new dataset
+         *       (with the proper fields).
+         *   <li>If authentication succeeded and this response is not empty, call {@link
+         *       android.service.autofill.FillCallback#onDatasetAuthentication(Dataset, int)}
+         *       passing
+         *       {@link android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_SUCCESS} in the
+         *       {@code flags} and {@code null} as the {@code dataset}.
+         * </ul>
+         *
+         * @param extras when set, will be passed back in the {@link
+         *     android.service.autofill.AutoFillService#onDatasetAuthenticationRequest(Bundle,
+         *     int)}, call so it could be used by the service to handle state.
+         * @param flags optional parameters, currently ignored.
+         */
+        public Builder requiresCustomAuthentication(@Nullable Bundle extras, int flags) {
+            return requiresAuthentication(null, extras, flags);
+        }
+
+        /**
+         * Requires dataset authentication through the Fingerprint sensor before auto-filling the
+         * activity with this dataset.
+         *
+         * <p>This method is typically called when the dataset contains sensitive information (for
+         * example, credit card information) and the provider requires the user to re-authenticate
+         * before using it.
+         *
+         * <p>Since the dataset is "locked" until the user authenticates it, typically this dataset
+         * name is masked (for example, "VISA....1234").
+         *
+         * <p>When the user selects this dataset, the Android System displays an UI affordance
+         * asking the user to use the fingerprint sensor unlock the dataset, and what happens after
+         * a successful fingerprint authentication depends on whether the dataset is empty (no
+         * fields, only the masked name) or not:
+         *
+         * <ul>
+         *   <li>If it's empty, the Android System will call {@link
+         *       android.service.autofill.AutoFillService#onDatasetAuthenticationRequest(Bundle,
+         *       int)} passing {@link
+         *       android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_SUCCESS}} in the
+         *       flags.
+         *   <li>If it's not empty, the activity will be auto-filled with its data.
+         * </ul>
+         *
+         * <p>If the fingerprint authentication fails, the Android System will call {@link
+         * android.service.autofill.AutoFillService#onDatasetAuthenticationRequest(Bundle, int)}
+         * passing {@link android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_ERROR} in the
+         * flags.
+         *
+         * <p><strong>NOTE: </note> the {@link android.service.autofill.AutoFillService} should use
+         * the {@link android.hardware.fingerprint.FingerprintManager} to check if fingerpint
+         * authentication is available before using this method, and use other alternatives (such as
+         * {@link #requiresCustomAuthentication(Bundle, int)}) if it is not: if this method is
+         * called when fingerprint is not available, Android System will call {@link
+         * android.service.autofill.AutoFillService#onDatasetAuthenticationRequest(Bundle, int)}
+         * passing {@link
+         * android.service.autofill.AutoFillService#FLAG_FINGERPRINT_AUTHENTICATION_NOT_AVAILABLE}
+         * in the flags, but it would be wasting system resources (and worsening the user
+         * experience) in the process.
+         *
+         * @param crypto object that will be authenticated.
+         * @param extras when set, will be passed back in the {@link
+         *     android.service.autofill.AutoFillService#onDatasetAuthenticationRequest(Bundle, int)}
+         *     call so it could be used by the service to handle state.
+         * @param flags optional parameters, currently ignored.
+         */
+        public Builder requiresFingerprintAuthentication(CryptoObject crypto,
+                @Nullable Bundle extras, int flags) {
+            // TODO(b/33197203): should we allow crypto to be null?
+            Preconditions.checkArgument(crypto != null, "must pass a CryptoObject");
+            return requiresAuthentication(crypto, extras, flags);
+        }
+
+        private Builder requiresAuthentication(CryptoObject cryptoObject, Bundle extras,
+                int flags) {
+            // There can be only one!
+            Preconditions.checkState(!mRequiresAuth,
+                    "requires-authentication methods already called");
+            // TODO(b/33197203): make sure that either this method or setExtras() is called, but
+            // not both
+            mExtras = extras;
+            mFlags = flags;
+            mRequiresAuth = true;
+            if (cryptoObject != null) {
+                mHasCryptoObject = true;
+                mCryptoOpId = cryptoObject.getOpId();
+            }
+            return this;
+        }
+
+        /**
          * Sets the value of a field.
          *
          * @param id id returned by {@link ViewNode#getAutoFillId()}.
@@ -121,15 +281,17 @@
         }
 
         /**
-         * Sets a {@link Bundle} that will be passed to subsequent calls to {@link AutoFillService}
-         * methods such as
-         * {@link AutoFillService#onSaveRequest(android.app.assist.AssistStructure, Bundle,
-         * android.os.CancellationSignal, android.service.autofill.SaveCallback)}, using
-         * {@link AutoFillService#EXTRA_DATASET_EXTRAS} as the key.
+         * Sets a {@link Bundle} that will be passed to subsequent calls to
+         * {@link android.service.autofill.AutoFillService} methods such as
+ * {@link android.service.autofill.AutoFillService#onSaveRequest(android.app.assist.AssistStructure,
+         * Bundle, android.service.autofill.SaveCallback)}, using
+         * {@link android.service.autofill.AutoFillService#EXTRA_DATASET_EXTRAS} as the key.
          *
          * <p>It can be used to keep service state in between calls.
          */
         public Builder setExtras(Bundle extras) {
+            // TODO(b/33197203): make sure that either this method or the requires-Authentication
+            // ones are called, but not both
             mExtras = Objects.requireNonNull(extras, "extras cannot be null");
             return this;
         }
@@ -158,6 +320,12 @@
         parcel.writeCharSequence(mName);
         parcel.writeList(mFields);
         parcel.writeBundle(mExtras);
+        parcel.writeInt(mFlags);
+        parcel.writeInt(mRequiresAuth ? 1 : 0);
+        parcel.writeInt(mHasCryptoObject ? 1 : 0);
+        if (mHasCryptoObject) {
+            parcel.writeLong(mCryptoOpId);
+        }
     }
 
     @SuppressWarnings("unchecked")
@@ -165,6 +333,10 @@
         mName = parcel.readCharSequence();
         mFields = parcel.readArrayList(null);
         mExtras = parcel.readBundle();
+        mFlags = parcel.readInt();
+        mRequiresAuth = parcel.readInt() == 1;
+        mHasCryptoObject = parcel.readInt() == 1;
+        mCryptoOpId = mHasCryptoObject ? parcel.readLong() : 0;
     }
 
     public static final Parcelable.Creator<Dataset> CREATOR = new Parcelable.Creator<Dataset>() {
diff --git a/core/java/android/view/autofill/FillResponse.java b/core/java/android/view/autofill/FillResponse.java
index 3a14767..48dbb84 100644
--- a/core/java/android/view/autofill/FillResponse.java
+++ b/core/java/android/view/autofill/FillResponse.java
@@ -18,11 +18,13 @@
 import static android.view.autofill.Helper.DEBUG;
 import static android.view.autofill.Helper.append;
 
+import android.annotation.Nullable;
 import android.app.Activity;
+import android.hardware.fingerprint.FingerprintManager.CryptoObject;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.service.autofill.AutoFillService;
+import android.service.autofill.FillCallback;
 
 import com.android.internal.util.Preconditions;
 
@@ -34,14 +36,16 @@
 import java.util.Set;
 
 /**
- * Response for a
- * {@link AutoFillService#onFillRequest(android.app.assist.AssistStructure, Bundle,
- * android.os.CancellationSignal, android.service.autofill.FillCallback)}
- * request.
+ * Response for a {@link
+ * android.service.autofill.AutoFillService#onFillRequest(android.app.assist.AssistStructure,
+ * Bundle, android.os.CancellationSignal, android.service.autofill.FillCallback)} request.
  *
  * <p>The response typically contains one or more {@link Dataset}s, each representing a set of
- * fields that can be auto-filled together. For example, for a login page with username/password
- * where the user only have one account in the service, the response could be:
+ * fields that can be auto-filled together, and the Android System displays a dataset picker UI
+ * affordance that the user must use before the {@link Activity} is filled with the dataset.
+ *
+ * <p>For example, for a login page with username/password where the user only has one account in
+ * the service, the response could be:
  *
  * <pre class="prettyprint">
  *  new FillResponse.Builder()
@@ -67,9 +71,9 @@
  *      .build();
  * </pre>
  *
- * <p>If the user does not have any data associated with this {@link Activity} but the service
- * wants to offer the user the option to save the data that was entered, then the service could
- * populate the response with {@code savableIds} instead of {@link Dataset}s:
+ * <p>If the user does not have any data associated with this {@link Activity} but the service wants
+ * to offer the user the option to save the data that was entered, then the service could populate
+ * the response with {@code savableIds} instead of {@link Dataset}s:
  *
  * <pre class="prettyprint">
  *  new FillResponse.Builder()
@@ -79,8 +83,8 @@
  *
  * <p>Similarly, there might be cases where the user data on the service is enough to populate some
  * fields but not all, and the service would still be interested on saving the other fields. In this
- * scenario, the service could populate the response with both {@link Dataset}s and
- * {@code savableIds}:
+ * scenario, the service could populate the response with both {@link Dataset}s and {@code
+ * savableIds}:
  *
  * <pre class="prettyprint">
  *   new FillResponse.Builder()
@@ -101,9 +105,9 @@
  * <p>If the service has multiple {@link Dataset}s with multiple options for some fields on each
  * dataset (for example, multiple accounts with both a home and work address), then it should
  * "partition" the {@link Activity} in sections and populate the response with just a subset of the
- * data that would fulfill the first section; then once the user fills the first section and taps
- * a field from the next section, the Android system would issue another request for that section,
- * and so on. For example, the first response could be:
+ * data that would fulfill the first section; then once the user fills the first section and taps a
+ * field from the next section, the Android system would issue another request for that section, and
+ * so on. For example, the first response could be:
  *
  * <pre class="prettyprint">
  *  new FillResponse.Builder()
@@ -134,19 +138,31 @@
  *      .build();
  * </pre>
  *
- * <p>Finally, the service can use the {@link FillResponse.Builder#setExtras(Bundle)} and/or
- * {@link Dataset.Builder#setExtras(Bundle)} methods to pass
- * a {@link Bundle} with service-specific data use to identify this response on future calls (like
- * {@link AutoFillService#onSaveRequest(android.app.assist.AssistStructure, Bundle,
- * android.os.CancellationSignal, android.service.autofill.SaveCallback)}) - such bundle will be
- * available as the {@link AutoFillService#EXTRA_RESPONSE_EXTRAS} extra in
- * that method's {@code extras} argument.
+ * <p>The service could require user authentication, either at the {@link FillResponse} or {@link
+ * Dataset} levels, prior to auto-filling the activity - see {@link
+ * FillResponse.Builder#requiresFingerprintAuthentication(CryptoObject, Bundle, int)}, {@link
+ * FillResponse.Builder#requiresCustomAuthentication(Bundle, int)}, {@link
+ * Dataset.Builder#requiresFingerprintAuthentication(CryptoObject, Bundle, int)}, and {@link
+ * Dataset.Builder#requiresCustomAuthentication(Bundle, int)} for details.
+ *
+ * <p>Finally, the service can use the {@link FillResponse.Builder#setExtras(Bundle)} and/or {@link
+ * Dataset.Builder#setExtras(Bundle)} methods to pass {@link Bundle}s with service-specific data use
+ * to identify this response on future calls (like {@link
+ * android.service.autofill.AutoFillService#onSaveRequest(android.app.assist.AssistStructure,
+ * Bundle, android.service.autofill.SaveCallback)}) - such bundles will be available as the
+ * {@link android.service.autofill.AutoFillService#EXTRA_RESPONSE_EXTRAS} and
+ * {@link android.service.autofill.AutoFillService#EXTRA_DATASET_EXTRAS} extras in that method's
+ * {@code extras} argument.
  */
 public final class FillResponse implements Parcelable {
 
     private final List<Dataset> mDatasets;
     private final AutoFillId[] mSavableIds;
     private final Bundle mExtras;
+    private final int mFlags;
+    private final boolean mRequiresAuth;
+    private final boolean mHasCryptoObject;
+    private final long mCryptoOpId;
 
     private FillResponse(Builder builder) {
         // TODO(b/33197203): make it immutable?
@@ -158,6 +174,10 @@
             mSavableIds[i++] = id;
         }
         mExtras = builder.mExtras;
+        mFlags = builder.mFlags;
+        mRequiresAuth = builder.mRequiresAuth;
+        mHasCryptoObject = builder.mHasCryptoObject;
+        mCryptoOpId = builder.mCryptoOpId;
     }
 
     /** @hide */
@@ -175,13 +195,161 @@
         return mExtras;
     }
 
+    /** @hide */
+    public int getFlags() {
+        return mFlags;
+    }
+
+    /** @hide */
+    public boolean isAuthRequired() {
+        return mRequiresAuth;
+    }
+
+    /** @hide */
+    public boolean hasCryptoObject() {
+        return mHasCryptoObject;
+    }
+
+    /** @hide */
+    public long getCryptoObjectOpId() {
+        return mCryptoOpId;
+    }
+
     /**
      * Builder for {@link FillResponse} objects.
      */
     public static final class Builder {
         private final List<Dataset> mDatasets = new ArrayList<>();
         private final Set<AutoFillId> mSavableIds = new HashSet<>();
-        private  Bundle mExtras;
+        private Bundle mExtras;
+        private int mFlags;
+        private boolean mRequiresAuth;
+        private boolean mHasCryptoObject;
+        private long mCryptoOpId;
+
+        /**
+         * Requires user authentication through the {@link android.service.autofill.AutoFillService}
+         * before handling an auto-fill request.
+         *
+         * <p>This method is typically called when the device (or the service) does not support
+         * fingerprint authentication (and hence it cannot use {@link
+         * #requiresFingerprintAuthentication(CryptoObject, Bundle, int)}) or when the service needs
+         * to use a custom authentication UI and is used in 2 scenarios:
+         *
+         * <ol>
+         *   <li>When the user data is encrypted and the service must authenticate an object that
+         *       will be used to decrypt it.
+         *   <li>When the service already acquired the user data but wants to confirm the user's
+         *       identity before the activity is filled with it.
+         * </ol>
+         *
+         * <p>When this method is called, the Android System displays an UI affordance asking the
+         * user to tap it to auto-fill the activity; if the user taps it, the Android System calls
+         * {@link
+         * android.service.autofill.AutoFillService#onFillResponseAuthenticationRequest(Bundle,
+         * int)} passing {@link
+         * android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_REQUESTED} in the flags and
+         * the same {@code extras} passed to this method. The service can then displays its custom
+         * authentication UI, and then call the proper method on {@link FillCallback} depending on
+         * the authentication result and whether this response already contains the {@link Dataset}s
+         * need to auto-fill the activity:
+         *
+         * <ul>
+         *   <li>If authentication failed, call {@link
+         *       FillCallback#onFillResponseAuthentication(int)} passing {@link
+         *       android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_ERROR} in the flags.
+         *   <li>If authentication succeeded and this response is empty (no datasets), call {@link
+         *       FillCallback#onSuccess(FillResponse)} with a new dataset (that does not require
+         *       authentication).
+         *   <li>If authentication succeeded and this response is not empty, call {@link
+         *       FillCallback#onFillResponseAuthentication(int)} passing {@link
+         *       android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_SUCCESS} in the flags.
+         * </ul>
+         *
+         * @param extras when set, will be passed back in the {@link
+         *     android.service.autofill.AutoFillService#onFillResponseAuthenticationRequest(Bundle,
+         *     int)} call so it could be used by the service to handle state.
+         * @param flags optional parameters, currently ignored.
+         */
+        public Builder requiresCustomAuthentication(@Nullable Bundle extras, int flags) {
+            return requiresAuthentication(null, extras, flags);
+        }
+
+        /**
+         * Requires user authentication through the Fingerprint sensor before handling an auto-fill
+         * request.
+         *
+         * <p>The {@link android.service.autofill.AutoFillService} typically uses this method in 2
+         * situations:
+         *
+         * <ol>
+         *   <li>When the user data is encrypted and the service must authenticate an object that
+         *       will be used to decrypt it.
+         *   <li>When the service already acquired the user data but wants to confirm the user's
+         *       identity before the activity is filled with it.
+         * </ol>
+         *
+         * <p>When this method is called, the Android System displays an UI affordance asking the
+         * user to use the fingerprint sensor to auto-fill the activity, and what happens after a
+         * successful fingerprint authentication depends on the number of {@link Dataset}s included
+         * in this response:
+         *
+         * <ul>
+         *   <li>If it's empty (scenario #1 above), the Android System will call {@link
+         *     android.service.autofill.AutoFillService#onFillResponseAuthenticationRequest(Bundle,
+         *       int)} passing {@link
+         *       android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_SUCCESS}} in the
+         *       flags.
+         *   <li>If it contains one dataset, the activity will be auto-filled right away.
+         *   <li>If it contains many datasets, the Android System will show dataset picker UI, and
+         *       then auto-fill the activity once the user select the proper datased.
+         * </ul>
+         *
+         * <p>If the fingerprint authentication fails, the Android System will call {@link
+         * android.service.autofill.AutoFillService#onFillResponseAuthenticationRequest(Bundle,
+         * int)} passing {@link android.service.autofill.AutoFillService#FLAG_AUTHENTICATION_ERROR}
+         * in the flags.
+         *
+         * <p><strong>NOTE: </note> the {@link android.service.autofill.AutoFillService} should use
+         * the {@link android.hardware.fingerprint.FingerprintManager} to check if fingerpint
+         * authentication is available before using this method, and use other alternatives (such as
+         * {@link #requiresCustomAuthentication(Bundle, int)}) if it is not: if this method is
+         * called when fingerprint is not available, Android System will call {@link
+         * android.service.autofill.AutoFillService#onFillResponseAuthenticationRequest(Bundle,
+         * int)} passing {@link
+         * android.service.autofill.AutoFillService#FLAG_FINGERPRINT_AUTHENTICATION_NOT_AVAILABLE}
+         * in the flags, but it would be wasting system resources (and worsening the user
+         * experience) in the process.
+         *
+         * @param crypto object that will be authenticated.
+         * @param extras when set, will be passed back in the {@link
+         *     android.service.autofill.AutoFillService#onFillResponseAuthenticationRequest(Bundle,
+         *     int)} call so it could be used by the service to handle state.
+         * @param flags optional parameters, currently ignored.
+         */
+        public Builder requiresFingerprintAuthentication(CryptoObject crypto,
+                @Nullable Bundle extras, int flags) {
+            // TODO(b/33197203): should we allow crypto to be null?
+            Preconditions.checkArgument(crypto != null, "must pass a CryptoObject");
+            return requiresAuthentication(crypto, extras, flags);
+        }
+
+        private Builder requiresAuthentication(CryptoObject cryptoObject, Bundle extras,
+                int flags) {
+            // There can be only one!
+            Preconditions.checkState(!mRequiresAuth,
+                    "requires-authentication methods already called");
+            // TODO(b/33197203): make sure that either this method or setExtras() is called, but
+            // not both
+            mExtras = extras;
+            mFlags = flags;
+            mRequiresAuth = true;
+            if (cryptoObject != null) {
+                mHasCryptoObject = true;
+                mCryptoOpId = cryptoObject.getOpId();
+            }
+            return this;
+        }
 
         /**
          * Adds a new {@link Dataset} to this response.
@@ -191,7 +359,6 @@
         public Builder addDataset(Dataset dataset) {
             Preconditions.checkNotNull(dataset, "dataset cannot be null");
             // TODO(b/33197203): check if name already exists
-            // TODO(b/33197203): check if authId already exists (and update javadoc)
             mDatasets.add(dataset);
             for (DatasetField field : dataset.getFields()) {
                 mSavableIds.add(field.getId());
@@ -201,13 +368,13 @@
 
         /**
          * Adds ids of additional fields that the service would be interested to save (through
-         * {@link AutoFillService#onSaveRequest(android.app.assist.AssistStructure, Bundle,
-         * android.os.CancellationSignal, android.service.autofill.SaveCallback)}) but were not
-         * indirectly set through {@link #addDataset(Dataset)}.
+         * {@link android.service.autofill.AutoFillService#onSaveRequest(
+         * android.app.assist.AssistStructure, Bundle, android.service.autofill.SaveCallback)})
+         * but were not indirectly set through {@link #addDataset(Dataset)}.
          *
          * <p>See {@link FillResponse} for examples.
          */
-        public Builder addSavableFields(AutoFillId...ids) {
+        public Builder addSavableFields(AutoFillId... ids) {
             for (AutoFillId id : ids) {
                 mSavableIds.add(id);
             }
@@ -215,15 +382,18 @@
         }
 
         /**
-         * Sets a {@link Bundle} that will be passed to subsequent calls to {@link AutoFillService}
-         * methods such as
-         * {@link AutoFillService#onSaveRequest(android.app.assist.AssistStructure, Bundle,
-         * android.os.CancellationSignal, android.service.autofill.SaveCallback)}, using
-         * {@link AutoFillService#EXTRA_RESPONSE_EXTRAS} as the key.
+         * Sets a {@link Bundle} that will be passed to subsequent calls to {@link
+         * android.service.autofill.AutoFillService} methods such as {@link
+         * android.service.autofill.AutoFillService#onSaveRequest(
+         * android.app.assist.AssistStructure, Bundle, android.service.autofill.SaveCallback)},
+         * using {@link
+         * android.service.autofill.AutoFillService#EXTRA_RESPONSE_EXTRAS} as the key.
          *
          * <p>It can be used when to keep service state in between calls.
          */
         public Builder setExtras(Bundle extras) {
+            // TODO(b/33197203): make sure that either this method or the requires-Authentication
+            // ones are called, but not both
             mExtras = Objects.requireNonNull(extras, "extras cannot be null");
             return this;
         }
@@ -246,7 +416,10 @@
         final StringBuilder builder = new StringBuilder("FillResponse: [datasets=")
                 .append(mDatasets).append(", savableIds=").append(Arrays.toString(mSavableIds))
                 .append(", extras=");
-        append(builder, mExtras);
+        append(builder, mExtras)
+            .append(", flags=").append(mFlags)
+            .append(", requiresAuth: ").append(mRequiresAuth)
+            .append(", hasCrypto: ").append(mHasCryptoObject);
         return builder.append(']').toString();
     }
 
@@ -264,6 +437,12 @@
         parcel.writeList(mDatasets);
         parcel.writeParcelableArray(mSavableIds, 0);
         parcel.writeBundle(mExtras);
+        parcel.writeInt(mFlags);
+        parcel.writeInt(mRequiresAuth ? 1 : 0);
+        parcel.writeInt(mHasCryptoObject ? 1 : 0);
+        if (mHasCryptoObject) {
+            parcel.writeLong(mCryptoOpId);
+        }
     }
 
     private FillResponse(Parcel parcel) {
@@ -271,6 +450,10 @@
         parcel.readList(mDatasets, null);
         mSavableIds = parcel.readParcelableArray(null, AutoFillId.class);
         mExtras = parcel.readBundle();
+        mFlags = parcel.readInt();
+        mRequiresAuth = parcel.readInt() == 1;
+        mHasCryptoObject = parcel.readInt() == 1;
+        mCryptoOpId = mHasCryptoObject ? parcel.readLong() : 0;
     }
 
     public static final Parcelable.Creator<FillResponse> CREATOR =
diff --git a/core/java/android/view/autofill/Helper.java b/core/java/android/view/autofill/Helper.java
index 772710e..14cf9e8 100644
--- a/core/java/android/view/autofill/Helper.java
+++ b/core/java/android/view/autofill/Helper.java
@@ -18,28 +18,33 @@
 
 import android.os.Bundle;
 
+import java.util.Arrays;
+import java.util.Objects;
 import java.util.Set;
 
 /** @hide */
 public final class Helper {
 
-    // TODO(b/33197203): set to false when stable
-    static final boolean DEBUG = true;
+    static final boolean DEBUG = true; // TODO(b/33197203): set to false when stable
     static final String REDACTED = "[REDACTED]";
 
-    static void append(StringBuilder builder, Bundle bundle) {
+    static StringBuilder append(StringBuilder builder, Bundle bundle) {
         if (bundle == null) {
             builder.append("N/A");
         } else if (!DEBUG) {
             builder.append(REDACTED);
         } else {
             final Set<String> keySet = bundle.keySet();
-            builder.append("[bundle with ").append(keySet.size()).append(" extras:");
+            builder.append("[Bundle with ").append(keySet.size()).append(" extras:");
             for (String key : keySet) {
-                builder.append(' ').append(key).append('=').append(bundle.get(key)).append(',');
+                final Object value = bundle.get(key);
+                builder.append(' ').append(key).append('=');
+                builder.append((value instanceof Object[])
+                        ? Arrays.toString((Objects[]) value) : value);
             }
             builder.append(']');
         }
+        return builder;
     }
 
     private Helper() {
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 72796cf..0657067 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -17,20 +17,34 @@
 package android.view.textclassifier;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.graphics.drawable.Drawable;
+import android.icu.text.BreakIterator;
 import android.net.Uri;
 import android.os.ParcelFileDescriptor;
 import android.text.SmartSelection;
+import android.text.Spannable;
 import android.text.TextUtils;
+import android.text.method.WordIterator;
+import android.text.style.ClickableSpan;
+import android.text.util.Linkify;
 import android.util.Log;
+import android.view.View;
 
 import com.android.internal.util.Preconditions;
 
 import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
 
 /**
  * Default implementation of the {@link TextClassifier} interface.
@@ -99,29 +113,7 @@
                     type = type.toLowerCase().trim();
                     // TODO: Added this log for debug only. Remove before release.
                     Log.d(LOG_TAG, String.format("Classification type: %s", type));
-                    final Intent intent;
-                    final String title;
-                    switch (type) {
-                        case TextClassifier.TYPE_EMAIL:
-                            intent = new Intent(Intent.ACTION_SENDTO);
-                            intent.setData(Uri.parse(String.format("mailto:%s", text)));
-                            title = mContext.getString(com.android.internal.R.string.email);
-                            return createClassificationResult(classified, type, intent, title);
-                        case TextClassifier.TYPE_PHONE:
-                            intent = new Intent(Intent.ACTION_DIAL);
-                            intent.setData(Uri.parse(String.format("tel:%s", text)));
-                            title = mContext.getString(com.android.internal.R.string.dial);
-                            return createClassificationResult(classified, type, intent, title);
-                        case TextClassifier.TYPE_ADDRESS:
-                            intent = new Intent(Intent.ACTION_VIEW);
-                            intent.setData(Uri.parse(String.format("geo:0,0?q=%s", text)));
-                            title = mContext.getString(com.android.internal.R.string.map);
-                            return createClassificationResult(classified, type, intent, title);
-                        default:
-                            // No classification type found. Return a no-op result.
-                            break;
-                        // TODO: Add other classification types.
-                    }
+                    return createClassificationResult(type, classified);
                 }
             }
         } catch (Throwable t) {
@@ -132,9 +124,18 @@
         return TextClassifier.NO_OP.getTextClassificationResult(text, startIndex, endIndex);
     }
 
+
     @Override
-    public LinksInfo getLinks(@NonNull CharSequence text, int linkMask) {
-        // TODO: Implement
+    public LinksInfo getLinks(CharSequence text, int linkMask) {
+        Preconditions.checkArgument(text != null);
+        try {
+            return LinksInfoFactory.create(
+                    mContext, getSmartSelection(), text.toString(), linkMask);
+        } catch (Throwable t) {
+            // Avoid throwing from this method. Log the error.
+            Log.e(LOG_TAG, "Error getting links info.", t);
+        }
+        // Getting here means something went wrong, return a NO_OP result.
         return TextClassifier.NO_OP.getLinks(text, linkMask);
     }
 
@@ -145,19 +146,23 @@
         return mSmartSelection;
     }
 
-    private TextClassificationResult createClassificationResult(
-            CharSequence text, String type, Intent intent, String label) {
-        TextClassificationResult.Builder builder = new TextClassificationResult.Builder()
+    private TextClassificationResult createClassificationResult(String type, CharSequence text) {
+        final Intent intent = IntentFactory.create(type, text.toString());
+        if (intent == null) {
+            return TextClassificationResult.EMPTY;
+        }
+
+        final TextClassificationResult.Builder builder = new TextClassificationResult.Builder()
                 .setText(text.toString())
                 .setEntityType(type, 1.0f /* confidence */)
                 .setIntent(intent)
                 .setOnClickListener(TextClassificationResult.createStartActivityOnClick(
                         mContext, intent))
-                .setLabel(label);
-        PackageManager pm = mContext.getPackageManager();
-        ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
-        // TODO: If the resolveInfo is the "chooser", do not set the package name and use a
-        // default icon for this classification type.
+                .setLabel(IntentFactory.getLabel(mContext, type));
+        final PackageManager pm = mContext.getPackageManager();
+        final ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
+        // TODO: If the resolveInfo is the "chooser", do not set the package name and use a default
+        // icon for this classification type.
         intent.setPackage(resolveInfo.activityInfo.packageName);
         Drawable icon = resolveInfo.activityInfo.loadIcon(pm);
         if (icon == null) {
@@ -177,4 +182,198 @@
         Preconditions.checkArgument(endIndex <= text.length());
         Preconditions.checkArgument(endIndex >= startIndex);
     }
+
+    /**
+     * Detects and creates links for specified text.
+     */
+    private static final class LinksInfoFactory {
+
+        private LinksInfoFactory() {}
+
+        public static LinksInfo create(
+                Context context, SmartSelection smartSelection, String text, int linkMask) {
+            final WordIterator wordIterator = new WordIterator();
+            wordIterator.setCharSequence(text, 0, text.length());
+            final List<SpanSpec> spans = new ArrayList<>();
+            int start = 0;
+            int end;
+            while ((end = wordIterator.nextBoundary(start)) != BreakIterator.DONE) {
+                final String token = text.substring(start, end);
+                if (TextUtils.isEmpty(token)) {
+                    continue;
+                }
+
+                final int[] selection = smartSelection.suggest(text, start, end);
+                final int selectionStart = selection[0];
+                final int selectionEnd = selection[1];
+                if (selectionStart >= 0 && selectionEnd <= text.length()
+                        && selectionStart <= selectionEnd) {
+                    final String type =
+                            smartSelection.classifyText(text, selectionStart, selectionEnd);
+                    if (matches(type, linkMask)) {
+                        final ClickableSpan span = createSpan(
+                                context, type, text.substring(selectionStart, selectionEnd));
+                        spans.add(new SpanSpec(selectionStart, selectionEnd, span));
+                    }
+                }
+                start = end;
+            }
+            return new LinksInfoImpl(text, avoidOverlaps(spans, text));
+        }
+
+        /**
+         * Returns true if the classification type matches the specified linkMask.
+         */
+        private static boolean matches(String type, int linkMask) {
+            if ((linkMask & Linkify.PHONE_NUMBERS) != 0
+                    && TextClassifier.TYPE_PHONE.equals(type)) {
+                return true;
+            }
+            if ((linkMask & Linkify.EMAIL_ADDRESSES) != 0
+                    && TextClassifier.TYPE_EMAIL.equals(type)) {
+                return true;
+            }
+            if ((linkMask & Linkify.MAP_ADDRESSES) != 0
+                    && TextClassifier.TYPE_ADDRESS.equals(type)) {
+                return true;
+            }
+            return false;
+        }
+
+        /**
+         * Trim the number of spans so that no two spans overlap.
+         *
+         * This algorithm first ensures that there is only one span per start index, then it
+         * makes sure that no two spans overlap.
+         */
+        private static List<SpanSpec> avoidOverlaps(List<SpanSpec> spans, String text) {
+            Collections.sort(spans, Comparator.comparingInt(span -> span.mStart));
+            // Group spans by start index. Take the longest span.
+            final Map<Integer, SpanSpec> reps = new LinkedHashMap<>();  // order matters.
+            final int size = spans.size();
+            for (int i = 0; i < size; i++) {
+                final SpanSpec span = spans.get(i);
+                final LinksInfoFactory.SpanSpec rep = reps.get(span.mStart);
+                if (rep == null || rep.mEnd < span.mEnd) {
+                    reps.put(span.mStart, span);
+                }
+            }
+            // Avoid span intersections. Take the longer span.
+            final LinkedList<SpanSpec> result = new LinkedList<>();
+            for (SpanSpec rep : reps.values()) {
+                if (result.isEmpty()) {
+                    result.add(rep);
+                    continue;
+                }
+
+                final SpanSpec last = result.getLast();
+                if (rep.mStart < last.mEnd) {
+                    // Spans intersect. Use the one with characters.
+                    if ((rep.mEnd - rep.mStart) > (last.mEnd - last.mStart)) {
+                        result.set(result.size() - 1, rep);
+                    }
+                } else {
+                    result.add(rep);
+                }
+            }
+            return result;
+        }
+
+        private static ClickableSpan createSpan(
+                final Context context, final String type, final String text) {
+            return new ClickableSpan() {
+                // TODO: Style this span.
+                @Override
+                public void onClick(View widget) {
+                    context.startActivity(IntentFactory.create(type, text));
+                }
+            };
+        }
+
+        /**
+         * Implementation of LinksInfo that adds ClickableSpans to the specified text.
+         */
+        private static final class LinksInfoImpl implements LinksInfo {
+
+            private final CharSequence mOriginalText;
+            private final List<SpanSpec> mSpans;
+
+            LinksInfoImpl(CharSequence originalText, List<SpanSpec> spans) {
+                mOriginalText = originalText;
+                mSpans = spans;
+            }
+
+            @Override
+            public boolean apply(@NonNull CharSequence text) {
+                Preconditions.checkArgument(text != null);
+                if (text instanceof Spannable && mOriginalText.toString().equals(text.toString())) {
+                    Spannable spannable = (Spannable) text;
+                    final int size = mSpans.size();
+                    for (int i = 0; i < size; i++) {
+                        final SpanSpec span = mSpans.get(i);
+                        spannable.setSpan(span.mSpan, span.mStart, span.mEnd, 0);
+                    }
+                    return true;
+                }
+                return false;
+            }
+        }
+
+        /**
+         * Span plus its start and end index.
+         */
+        private static final class SpanSpec {
+
+            private final int mStart;
+            private final int mEnd;
+            private final ClickableSpan mSpan;
+
+            SpanSpec(int start, int end, ClickableSpan span) {
+                mStart = start;
+                mEnd = end;
+                mSpan = span;
+            }
+        }
+    }
+
+    /**
+     * Creates intents based on the classification type.
+     */
+    private static final class IntentFactory {
+
+        private IntentFactory() {}
+
+        @Nullable
+        public static Intent create(String type, String text) {
+            switch (type) {
+                case TextClassifier.TYPE_EMAIL:
+                    return new Intent(Intent.ACTION_SENDTO)
+                            .setData(Uri.parse(String.format("mailto:%s", text)));
+                case TextClassifier.TYPE_PHONE:
+                    return new Intent(Intent.ACTION_DIAL)
+                            .setData(Uri.parse(String.format("tel:%s", text)));
+                case TextClassifier.TYPE_ADDRESS:
+                    return new Intent(Intent.ACTION_VIEW)
+                            .setData(Uri.parse(String.format("geo:0,0?q=%s", text)));
+                default:
+                    return null;
+                // TODO: Add other classification types.
+            }
+        }
+
+        @Nullable
+        public static String getLabel(Context context, String type) {
+            switch (type) {
+                case TextClassifier.TYPE_EMAIL:
+                    return context.getString(com.android.internal.R.string.email);
+                case TextClassifier.TYPE_PHONE:
+                    return context.getString(com.android.internal.R.string.dial);
+                case TextClassifier.TYPE_ADDRESS:
+                    return context.getString(com.android.internal.R.string.map);
+                default:
+                    return null;
+                // TODO: Add other classification types.
+            }
+        }
+    }
 }
diff --git a/core/java/android/view/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java
index 729eb8d..2e2056c 100644
--- a/core/java/android/view/textservice/SpellCheckerSession.java
+++ b/core/java/android/view/textservice/SpellCheckerSession.java
@@ -97,7 +97,6 @@
     private final SpellCheckerInfo mSpellCheckerInfo;
     private final SpellCheckerSessionListener mSpellCheckerSessionListener;
     private final SpellCheckerSessionListenerImpl mSpellCheckerSessionListenerImpl;
-    private final SpellCheckerSubtype mSubtype;
 
     private boolean mIsUsed;
 
@@ -121,8 +120,7 @@
      * @hide
      */
     public SpellCheckerSession(
-            SpellCheckerInfo info, ITextServicesManager tsm, SpellCheckerSessionListener listener,
-            SpellCheckerSubtype subtype) {
+            SpellCheckerInfo info, ITextServicesManager tsm, SpellCheckerSessionListener listener) {
         if (info == null || listener == null || tsm == null) {
             throw new NullPointerException();
         }
@@ -132,7 +130,6 @@
         mTextServicesManager = tsm;
         mIsUsed = true;
         mSpellCheckerSessionListener = listener;
-        mSubtype = subtype;
     }
 
     /**
@@ -218,7 +215,8 @@
         mSpellCheckerSessionListener.onGetSentenceSuggestions(suggestionInfos);
     }
 
-    private static class SpellCheckerSessionListenerImpl extends ISpellCheckerSessionListener.Stub {
+    private static final class SpellCheckerSessionListenerImpl
+            extends ISpellCheckerSessionListener.Stub {
         private static final int TASK_CANCEL = 1;
         private static final int TASK_GET_SUGGESTIONS_MULTIPLE = 2;
         private static final int TASK_CLOSE = 3;
@@ -366,7 +364,7 @@
             }
         }
 
-        public synchronized void onServiceConnected(ISpellCheckerSession session) {
+        public void onServiceConnected(ISpellCheckerSession session) {
             synchronized (this) {
                 switch (mState) {
                     case STATE_WAIT_CONNECTION:
@@ -408,9 +406,9 @@
                             + Integer.toHexString(mISpellCheckerSession.hashCode())
                             + " mPendingTasks.size()=" + mPendingTasks.size());
                 }
-            }
-            while (!mPendingTasks.isEmpty()) {
-                processTask(session, mPendingTasks.poll(), false);
+                while (!mPendingTasks.isEmpty()) {
+                    processTask(session, mPendingTasks.poll(), false);
+                }
             }
         }
 
@@ -529,7 +527,7 @@
         public void onGetSentenceSuggestions(SentenceSuggestionsInfo[] results);
     }
 
-    private static class InternalListener extends ITextServicesSessionListener.Stub {
+    private static final class InternalListener extends ITextServicesSessionListener.Stub {
         private final SpellCheckerSessionListenerImpl mParentSpellCheckerSessionListenerImpl;
 
         public InternalListener(SpellCheckerSessionListenerImpl spellCheckerSessionListenerImpl) {
@@ -547,7 +545,7 @@
         super.finalize();
         if (mIsUsed) {
             Log.e(TAG, "SpellCheckerSession was not finished properly." +
-                    "You should call finishShession() when you finished to use a spell checker.");
+                    "You should call finishSession() when you finished to use a spell checker.");
             close();
         }
     }
diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java
index 0f168f3..b4e6c56 100644
--- a/core/java/android/view/textservice/TextServicesManager.java
+++ b/core/java/android/view/textservice/TextServicesManager.java
@@ -171,8 +171,7 @@
         if (subtypeInUse == null) {
             return null;
         }
-        final SpellCheckerSession session = new SpellCheckerSession(
-                sci, mService, listener, subtypeInUse);
+        final SpellCheckerSession session = new SpellCheckerSession(sci, mService, listener);
         try {
             mService.getSpellCheckerService(sci.getId(), subtypeInUse.getLocale(),
                     session.getTextServicesSessionListener(),
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 8cedb17..47c4cf38 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2548,7 +2548,7 @@
     }
 
     private boolean isItemClickable(View view) {
-        return !view.hasFocusable();
+        return !view.hasFocusable(false);
     }
 
     /**
@@ -2824,7 +2824,7 @@
             final View v = getChildAt(mSelectedPosition - mFirstPosition);
 
             if (v != null) {
-                if (v.hasFocusable()) return;
+                if (v.hasFocusable(false)) return;
                 v.setPressed(true);
             }
             setPressed(true);
@@ -3428,7 +3428,7 @@
             if (mTouchMode == TOUCH_MODE_DOWN) {
                 mTouchMode = TOUCH_MODE_TAP;
                 final View child = getChildAt(mMotionPosition - mFirstPosition);
-                if (child != null && !child.hasFocusable()) {
+                if (child != null && !child.hasFocusable(false)) {
                     mLayoutMode = LAYOUT_NORMAL;
 
                     if (!mDataChanged) {
@@ -4005,7 +4005,7 @@
 
                 final float x = ev.getX();
                 final boolean inList = x > mListPadding.left && x < getWidth() - mListPadding.right;
-                if (inList && !child.hasFocusable()) {
+                if (inList && !child.hasFocusable(false)) {
                     if (mPerformClick == null) {
                         mPerformClick = new PerformClick();
                     }
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index 6706790..07ad872 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -24,10 +24,7 @@
 import android.text.method.ArrowKeyMovementMethod;
 import android.text.method.MovementMethod;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.autofill.AutoFillType;
-import android.view.autofill.AutoFillValue;
 
 /*
  * This is supposed to be a *very* thin veneer over TextView.
@@ -158,24 +155,4 @@
             info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SET_TEXT);
         }
     }
-
-    // TODO(b/33197203): add unit/CTS tests for auto-fill methods
-
-    @Override
-    public void autoFill(AutoFillValue value) {
-        final CharSequence text = value.getTextValue();
-
-        if (text == null) {
-            Log.w(VIEW_LOG_TAG, "EditText.autoFill(): no text on AutoFillValue");
-            return;
-        }
-        setText(text);
-    }
-
-    @Override
-    public AutoFillType getAutoFillType() {
-        // TODO(b/33197203): ideally it should return a constant, but value returned by
-        // getInputType() can change.
-        return AutoFillType.forText(getInputType());
-    }
 }
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 46324a3..5199b26 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -232,7 +232,7 @@
                         mDecorView.getLayoutParams();
 
                 updateAboveAnchor(findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff,
-                        p.width, p.height, mAnchoredGravity));
+                        p.width, p.height, mAnchoredGravity, false));
                 update(p.x, p.y, -1, -1, true);
             }
         }
@@ -1237,7 +1237,7 @@
         preparePopup(p);
 
         final boolean aboveAnchor = findDropDownPosition(anchor, p, xoff, yoff,
-                p.width, p.height, gravity);
+                p.width, p.height, gravity, mAllowScrollingAnchorParent);
         updateAboveAnchor(aboveAnchor);
         p.accessibilityIdOfAnchor = (anchor != null) ? anchor.getAccessibilityViewId() : -1;
 
@@ -1529,10 +1529,12 @@
      * @param xOffset absolute horizontal offset from the left of the anchor
      * @param yOffset absolute vertical offset from the top of the anchor
      * @param gravity horizontal gravity specifying popup alignment
+     * @param allowScroll whether the anchor view's parent may be scrolled
+     *                    when the popup window doesn't fit on screen
      * @return true if the popup is translated upwards to fit on screen
      */
     private boolean findDropDownPosition(View anchor, WindowManager.LayoutParams outParams,
-            int xOffset, int yOffset, int width, int height, int gravity) {
+            int xOffset, int yOffset, int width, int height, int gravity, boolean allowScroll) {
         final int anchorHeight = anchor.getHeight();
         final int anchorWidth = anchor.getWidth();
         if (mOverlapAnchor) {
@@ -1586,7 +1588,7 @@
             final int scrollY = anchor.getScrollY();
             final Rect r = new Rect(scrollX, scrollY, scrollX + width + xOffset,
                     scrollY + height + anchorHeight + yOffset);
-            if (mAllowScrollingAnchorParent && anchor.requestRectangleOnScreen(r, true)) {
+            if (allowScroll && anchor.requestRectangleOnScreen(r, true)) {
                 // Reset for the new anchor position.
                 anchor.getLocationInWindow(drawingLocation);
                 outParams.x = drawingLocation[0] + xOffset;
@@ -2182,15 +2184,19 @@
         }
 
         final boolean aboveAnchor = findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff,
-                width, height, gravity);
+                width, height, gravity, mAllowScrollingAnchorParent);
         updateAboveAnchor(aboveAnchor);
 
         final boolean paramsChanged = oldGravity != p.gravity || oldX != p.x || oldY != p.y
                 || oldWidth != p.width || oldHeight != p.height;
-        // If width and mWidth were both < 0 then we have a MATCH_PARENT/WRAP_CONTENT case.
-        // findDropDownPosition will have resolved this to absolute values,
-        // but we don't want to update mWidth/mHeight to these absolute values.
-        update(p.x, p.y, width < 0 ? width : p.width, height < 0 ? height : p.height, paramsChanged);
+
+        // If width and mWidth were both < 0 then we have a MATCH_PARENT or
+        // WRAP_CONTENT case. findDropDownPosition will have resolved this to
+        // absolute values, but we don't want to update mWidth/mHeight to these
+        // absolute values.
+        final int newWidth = width < 0 ? width : p.width;
+        final int newHeight = height < 0 ? height : p.height;
+        update(p.x, p.y, newWidth, newHeight, paramsChanged);
     }
 
     /**
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 266ff75..ec2adfb 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -2058,6 +2058,18 @@
     }
 
     /**
+     * Returns whether the ProgressBar is animating or not. This is essentially the same
+     * as whether the ProgressBar is {@link #isIndeterminate() indeterminate} and visible,
+     * as indeterminate ProgressBars are always animating, and non-indeterminate
+     * ProgressBars are not animating.
+     *
+     * @return true if the ProgressBar is animating, false otherwise.
+     */
+    public boolean isAnimating() {
+        return isIndeterminate() && getWindowVisibility() == VISIBLE && isShown();
+    }
+
+    /**
      * Command for sending an accessibility event.
      */
     private class AccessibilityEventSender implements Runnable {
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index eb46b9f..359d04e 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -3302,7 +3302,7 @@
      * Applies the views asynchronously, moving as much of the task on the background
      * thread as possible.
      *
-     * @see {@link #apply(Context, ViewGroup)}
+     * @see #apply(Context, ViewGroup)
      * @param context Default context to use
      * @param parent Parent that the resulting view hierarchy will be attached to. This method
      * does <strong>not</strong> attach the hierarchy. The caller should do so when appropriate.
@@ -3457,7 +3457,7 @@
      * Applies all the actions to the provided view, moving as much of the task on the background
      * thread as possible.
      *
-     * @see {@link #reapply(Context, View)}
+     * @see #reapply(Context, View)
      * @param context Default context to use
      * @param v The view to apply the actions to.  This should be the result of
      * the {@link #apply(Context,ViewGroup)} call.
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 072fe4a..8ec52bd 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -137,6 +137,8 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.AnimationUtils;
 import android.view.autofill.AutoFillManager;
+import android.view.autofill.AutoFillType;
+import android.view.autofill.AutoFillValue;
 import android.view.inputmethod.BaseInputConnection;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.CorrectionInfo;
@@ -785,6 +787,7 @@
         ColorStateList textColorLink = null;
         int textSize = 15;
         String fontFamily = null;
+        Typeface fontTypeface = null;
         boolean fontFamilyExplicit = false;
         int typefaceIndex = -1;
         int styleIndex = -1;
@@ -847,7 +850,14 @@
                         break;
 
                     case com.android.internal.R.styleable.TextAppearance_fontFamily:
-                        fontFamily = appearance.getString(attr);
+                        try {
+                            fontTypeface = appearance.getFont(attr);
+                        } catch (UnsupportedOperationException e) {
+                            // Expected if it is not a font resource.
+                        }
+                        if (fontTypeface == null) {
+                            fontFamily = appearance.getString(attr);
+                        }
                         break;
 
                     case com.android.internal.R.styleable.TextAppearance_textStyle:
@@ -1151,7 +1161,14 @@
                     break;
 
                 case com.android.internal.R.styleable.TextView_fontFamily:
-                    fontFamily = a.getString(attr);
+                    try {
+                        fontTypeface = appearance.getFont(attr);
+                    } catch (UnsupportedOperationException e) {
+                        // Expected if it is not a font resource.
+                    }
+                    if (fontTypeface == null) {
+                        fontFamily = appearance.getString(attr);
+                    }
                     fontFamilyExplicit = true;
                     break;
 
@@ -1501,7 +1518,7 @@
         if (typefaceIndex != -1 && !fontFamilyExplicit) {
             fontFamily = null;
         }
-        setTypefaceFromAttrs(fontFamily, typefaceIndex, styleIndex);
+        setTypefaceFromAttrs(fontTypeface, fontFamily, typefaceIndex, styleIndex);
 
         if (shadowcolor != 0) {
             setShadowLayer(r, dx, dy, shadowcolor);
@@ -1794,14 +1811,15 @@
         }
     }
 
-    private void setTypefaceFromAttrs(String familyName, int typefaceIndex, int styleIndex) {
-        Typeface tf = null;
-        if (familyName != null) {
+    private void setTypefaceFromAttrs(Typeface fontTypeface, String familyName, int typefaceIndex,
+            int styleIndex) {
+        Typeface tf = fontTypeface;
+        if (tf == null && familyName != null) {
             tf = Typeface.create(familyName, styleIndex);
-            if (tf != null) {
-                setTypeface(tf);
-                return;
-            }
+        }
+        if (tf != null) {
+            setTypeface(tf);
+            return;
         }
         switch (typefaceIndex) {
             case SANS:
@@ -3099,10 +3117,19 @@
             setLinkTextColor(textColorLink);
         }
 
-        final String fontFamily = ta.getString(R.styleable.TextAppearance_fontFamily);
+        Typeface fontTypeface = null;
+        String fontFamily = null;
+        try {
+            fontTypeface = ta.getFont(R.styleable.TextAppearance_fontFamily);
+        } catch (UnsupportedOperationException e) {
+            // Expected if it is not a font resource.
+        }
+        if (fontTypeface == null) {
+            fontFamily = ta.getString(R.styleable.TextAppearance_fontFamily);
+        }
         final int typefaceIndex = ta.getInt(R.styleable.TextAppearance_typeface, -1);
         final int styleIndex = ta.getInt(R.styleable.TextAppearance_textStyle, -1);
-        setTypefaceFromAttrs(fontFamily, typefaceIndex, styleIndex);
+        setTypefaceFromAttrs(fontTypeface, fontFamily, typefaceIndex, styleIndex);
 
         final int shadowColor = ta.getInt(R.styleable.TextAppearance_shadowColor, 0);
         if (shadowColor != 0) {
@@ -5163,15 +5190,15 @@
         boolean forceUpdate = false;
         if (isPassword) {
             setTransformationMethod(PasswordTransformationMethod.getInstance());
-            setTypefaceFromAttrs(null /* fontFamily */, MONOSPACE, 0);
+            setTypefaceFromAttrs(null/* fontTypeface */, null /* fontFamily */, MONOSPACE, 0);
         } else if (isVisiblePassword) {
             if (mTransformation == PasswordTransformationMethod.getInstance()) {
                 forceUpdate = true;
             }
-            setTypefaceFromAttrs(null /* fontFamily */, MONOSPACE, 0);
+            setTypefaceFromAttrs(null/* fontTypeface */, null /* fontFamily */, MONOSPACE, 0);
         } else if (wasPassword || wasVisiblePassword) {
             // not in password mode, clean up typeface and transformation
-            setTypefaceFromAttrs(null /* fontFamily */, -1, -1);
+            setTypefaceFromAttrs(null/* fontTypeface */, null /* fontFamily */, -1, -1);
             if (mTransformation == PasswordTransformationMethod.getInstance()) {
                 forceUpdate = true;
             }
@@ -9026,15 +9053,6 @@
                 Spannable sp = (Spannable) mText;
                 MetaKeyKeyListener.resetMetaState(sp);
             }
-        } else {
-            final AutoFillManager afm = mContext.getSystemService(AutoFillManager.class);
-            if (afm != null) {
-                if (DEBUG_AUTOFILL) {
-                    Log.v(LOG_TAG, "onFocusChanged(): id=" + getAutoFillViewId() + ", focused= "
-                            + focused);
-                }
-                afm.updateAutoFillInput(this, AutoFillManager.FLAG_UPDATE_UI_HIDE);
-            }
         }
 
         startStopMarquee(focused);
@@ -9754,6 +9772,23 @@
         structure.setHint(getHint());
     }
 
+    // TODO(b/33197203): add unit/CTS tests for auto-fill methods
+
+    @Override
+    public void autoFill(AutoFillValue value) {
+        final CharSequence text = value.getTextValue();
+
+        if (text != null && isTextEditable()) {
+            setText(text);
+        }
+    }
+
+    @Override
+    @Nullable
+    public AutoFillType getAutoFillType() {
+        return isTextEditable() ? AutoFillType.forText(getInputType()) : null;
+    }
+
     /** @hide */
     @Override
     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
@@ -10615,7 +10650,7 @@
     protected void viewClicked(InputMethodManager imm) {
         final AutoFillManager afm = mContext.getSystemService(AutoFillManager.class);
         if (afm != null) {
-            if (DEBUG_AUTOFILL) Log.v(LOG_TAG, "viewClicked(): id=" + getAutoFillViewId());
+            if (DEBUG_AUTOFILL) Log.v(LOG_TAG, "viewClicked(): id=" + getAccessibilityViewId());
 
             // TODO(b/33197203): integrate with onFocus and/or move to view?
             afm.updateAutoFillInput(this, AutoFillManager.FLAG_UPDATE_UI_SHOW);
diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java
index 00faf65..4071ff4 100644
--- a/core/java/com/android/internal/app/ResolverListController.java
+++ b/core/java/com/android/internal/app/ResolverListController.java
@@ -69,14 +69,14 @@
     }
 
     @VisibleForTesting
-    ResolveInfo getLastChosen() throws RemoteException {
+    public ResolveInfo getLastChosen() throws RemoteException {
         return AppGlobals.getPackageManager().getLastChosenActivity(
                 mTargetIntent, mTargetIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
                 PackageManager.MATCH_DEFAULT_ONLY);
     }
 
     @VisibleForTesting
-    void setLastChosen(Intent intent, IntentFilter filter, int match)
+    public void setLastChosen(Intent intent, IntentFilter filter, int match)
             throws RemoteException {
         AppGlobals.getPackageManager().setLastChosenActivity(intent,
                 intent.resolveType(mContext.getContentResolver()),
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
index a1eac36..81db93d 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
@@ -69,5 +69,6 @@
     boolean isBoundWidgetPackage(String packageName, int userId);
     boolean requestPinAppWidget(String packageName, in ComponentName providerComponent,
             in IntentSender resultIntent);
+    boolean isRequestPinAppWidgetSupported();
 }
 
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index c08cd72..3e231d0 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -266,43 +266,6 @@
         }
     }
 
-    private static InputMethodListBuilder getMinimumKeyboardSetWithoutSystemLocale(
-            final ArrayList<InputMethodInfo> imis, final Context context,
-            @Nullable final Locale fallbackLocale) {
-        // Before the system becomes ready, we pick up at least one keyboard in the following order.
-        // The first user (device owner) falls into this category.
-        // 1. checkDefaultAttribute: true, locale: fallbackLocale, checkCountry: true
-        // 2. checkDefaultAttribute: false, locale: fallbackLocale, checkCountry: true
-        // 3. checkDefaultAttribute: true, locale: fallbackLocale, checkCountry: false
-        // 4. checkDefaultAttribute: false, locale: fallbackLocale, checkCountry: false
-        // TODO: We should check isAsciiCapable instead of relying on fallbackLocale.
-
-        final InputMethodListBuilder builder = new InputMethodListBuilder();
-        builder.fillImes(imis, context, true /* checkDefaultAttribute */, fallbackLocale,
-                true /* checkCountry */, SUBTYPE_MODE_KEYBOARD);
-        if (!builder.isEmpty()) {
-            return builder;
-        }
-        builder.fillImes(imis, context, false /* checkDefaultAttribute */, fallbackLocale,
-                true /* checkCountry */, SUBTYPE_MODE_KEYBOARD);
-        if (!builder.isEmpty()) {
-            return builder;
-        }
-        builder.fillImes(imis, context, true /* checkDefaultAttribute */, fallbackLocale,
-                false /* checkCountry */, SUBTYPE_MODE_KEYBOARD);
-        if (!builder.isEmpty()) {
-            return builder;
-        }
-        builder.fillImes(imis, context, false /* checkDefaultAttribute */, fallbackLocale,
-                false /* checkCountry */, SUBTYPE_MODE_KEYBOARD);
-        if (!builder.isEmpty()) {
-            return builder;
-        }
-        Slog.w(TAG, "No software keyboard is found. imis=" + Arrays.toString(imis.toArray())
-                + " fallbackLocale=" + fallbackLocale);
-        return builder;
-    }
-
     private static InputMethodListBuilder getMinimumKeyboardSetWithSystemLocale(
             final ArrayList<InputMethodInfo> imis, final Context context,
             @Nullable final Locale systemLocale, @Nullable final Locale fallbackLocale) {
@@ -353,21 +316,10 @@
     }
 
     public static ArrayList<InputMethodInfo> getDefaultEnabledImes(final Context context,
-            final boolean isSystemReady, final ArrayList<InputMethodInfo> imis) {
+            final ArrayList<InputMethodInfo> imis) {
         final Locale fallbackLocale = getFallbackLocaleForDefaultIme(imis, context);
-        if (!isSystemReady) {
-            // When the system is not ready, the system locale is not stable and reliable. Hence
-            // we will pick up IMEs that support software keyboard based on the fallback locale.
-            // Also pick up suitable IMEs regardless of the software keyboard support.
-            // (e.g. Voice IMEs)
-            return getMinimumKeyboardSetWithoutSystemLocale(imis, context, fallbackLocale)
-                    .fillImes(imis, context, true /* checkDefaultAttribute */, fallbackLocale,
-                            true /* checkCountry */, SUBTYPE_MODE_ANY)
-                    .build();
-        }
-
-        // When the system is ready, we will primarily rely on the system locale, but also keep
-        // relying on the fallback locale as a last resort.
+        // We will primarily rely on the system locale, but also keep relying on the fallback locale
+        // as a last resort.
         // Also pick up suitable IMEs regardless of the software keyboard support (e.g. Voice IMEs),
         // then pick up suitable auxiliary IMEs when necessary (e.g. Voice IMEs with "automatic"
         // subtype)
diff --git a/core/java/com/android/internal/logging/legacy/CounterParser.java b/core/java/com/android/internal/logging/legacy/CounterParser.java
deleted file mode 100644
index f318503..0000000
--- a/core/java/com/android/internal/logging/legacy/CounterParser.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import android.util.Log;
-
-/**
- * Parse the Android counter event logs.
- * @hide
- */
-public class CounterParser extends TagParser {
-    private static final String TAG = "CounterParser";
-    private static final int EVENTLOG_TAG = 524290;
-
-    @Override
-    public int getTag() {
-        return EVENTLOG_TAG;
-    }
-
-    @Override
-    public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
-        final boolean debug = Util.debug();
-        if (operands.length >= 2) {
-            try {
-                String name = ((String) operands[0]);
-                int value = (Integer) operands[1];
-                logCount(logger, name, value);
-            } catch (ClassCastException e) {
-                if (debug) {
-                    Log.d(TAG, "unexpected operand type", e);
-                }
-            }
-        } else if (debug) {
-            Log.d(TAG, "wrong number of operands: " + operands.length);
-        }
-    }
-
-    protected void logCount(TronLogger logger, String name, int value) {
-        logger.incrementBy(TronCounters.TRON_AOSP_PREFIX + name, value);
-    }
-}
diff --git a/core/java/com/android/internal/logging/legacy/EventLogCollector.java b/core/java/com/android/internal/logging/legacy/EventLogCollector.java
index eba7d0f..46e70ea 100644
--- a/core/java/com/android/internal/logging/legacy/EventLogCollector.java
+++ b/core/java/com/android/internal/logging/legacy/EventLogCollector.java
@@ -45,19 +45,6 @@
 
     private EventLogCollector() {
         mTagParsers = new ArrayMap<>();
-        addParser(new SysuiViewVisibilityParser());
-        addParser(new SysuiActionParser());
-        addParser(new SysuiQueryParser());
-        addParser(new NotificationPanelRevealedParser());
-        addParser(new NotificationPanelHiddenParser());
-        addParser(new NotificationClickedParser());
-        addParser(new NotificationActionClickedParser());
-        addParser(new NotificationCanceledParser());
-        addParser(new NotificationVisibilityParser());
-        addParser(new NotificationAlertParser());
-        addParser(new NotificationExpansionParser());
-        addParser(new CounterParser());
-        addParser(new HistogramParser());
         addParser(new LockscreenGestureParser());
         addParser(new StatusBarStateParser());
         addParser(new PowerScreenStateParser());
diff --git a/core/java/com/android/internal/logging/legacy/HistogramParser.java b/core/java/com/android/internal/logging/legacy/HistogramParser.java
deleted file mode 100644
index bb7e75c..0000000
--- a/core/java/com/android/internal/logging/legacy/HistogramParser.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.logging.legacy;
-
-/**
- * Parse the Android histogram event logs.
- * @hide
- */
-public class HistogramParser extends CounterParser {
-    private static final String TAG = "HistogramParser";
-    private static final int EVENTLOG_TAG = 524291;
-
-    @Override
-    public int getTag() {
-        return EVENTLOG_TAG;
-    }
-
-    @Override
-    protected void logCount(TronLogger logger, String name, int value) {
-        logger.incrementIntHistogram("tron_varz_" + name, value);
-    }
-}
diff --git a/core/java/com/android/internal/logging/legacy/NotificationActionClickedParser.java b/core/java/com/android/internal/logging/legacy/NotificationActionClickedParser.java
deleted file mode 100644
index 79f3eb8..0000000
--- a/core/java/com/android/internal/logging/legacy/NotificationActionClickedParser.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import android.util.Log;
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-/**
- * Parse the Android notification action button interaction event logs.
- * @hide
- */
-public class NotificationActionClickedParser extends TagParser {
-    private static final String TAG = "NotificationAction";
-    private static final int EVENTLOG_TAG = 27521;
-
-    private final NotificationKey mKey;
-
-    public NotificationActionClickedParser() {
-        mKey = new NotificationKey();
-    }
-
-    @Override
-    public int getTag() {
-        return EVENTLOG_TAG;
-    }
-
-    @Override
-    public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
-        final boolean debug = Util.debug();
-        if (operands.length > 1) {
-            try {
-                if (mKey.parse((String) operands[0])) {
-                    int index = (Integer) operands[1];
-                    parseTimes(operands, 2);
-                    LogMaker proto = logger.obtain();
-                    proto.setCategory(MetricsEvent.NOTIFICATION_ITEM_ACTION);
-                    proto.setType(MetricsEvent.TYPE_ACTION);
-                    proto.setSubtype(index);
-                    proto.setTimestamp(eventTimeMs);
-                    proto.setPackageName(mKey.mPackageName);
-                    proto.addTaggedData(MetricsEvent.NOTIFICATION_ID, mKey.mId);
-                    proto.addTaggedData(MetricsEvent.NOTIFICATION_TAG, mKey.mTag);
-                    filltimes(proto);
-                    logger.addEvent(proto);
-                } else if (debug) {
-                    Log.e(TAG, "unable to parse key.");
-                }
-            } catch (ClassCastException e) {
-                if (debug) {
-                    Log.e(TAG, "unexpected operand type: ", e);
-                }
-            }
-        } else if (debug) {
-            Log.w(TAG, "wrong number of operands: " + operands.length);
-        }
-    }
-}
diff --git a/core/java/com/android/internal/logging/legacy/NotificationAlertParser.java b/core/java/com/android/internal/logging/legacy/NotificationAlertParser.java
deleted file mode 100644
index 9548fb0..0000000
--- a/core/java/com/android/internal/logging/legacy/NotificationAlertParser.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import android.util.Log;
-
-import android.metrics.LogMaker;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-/**
- * Parse the new Android notification alert event logs.
- * @hide
- */
-public class NotificationAlertParser extends TagParser {
-    private static final String TAG = "NotificationAlertParser";
-    private static final int EVENTLOG_TAG = 27532;
-
-    @VisibleForTesting
-    static final int BUZZ = 0x00000001;
-    @VisibleForTesting
-    static final int BEEP = 0x00000002;
-    @VisibleForTesting
-    static final int BLINK = 0x00000004;
-
-    private final NotificationKey mKey;
-
-    public NotificationAlertParser() {
-        mKey = new NotificationKey();
-    }
-
-    @Override
-    public int getTag() {
-        return EVENTLOG_TAG;
-    }
-
-    @Override
-    public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
-        final boolean debug = Util.debug();
-        if (operands.length > 3) {
-            try {
-                final String keyString = (String) operands[0];
-                final boolean buzz = ((Integer) operands[1]) == 1;
-                final boolean beep = ((Integer) operands[2]) == 1;
-                final boolean blink = ((Integer) operands[3]) == 1;
-
-                if (mKey.parse(keyString)) {
-                    LogMaker proto = logger.obtain();
-                    proto.setCategory(MetricsEvent.NOTIFICATION_ALERT);
-                    proto.setType(MetricsEvent.TYPE_OPEN);
-                    proto.setSubtype((buzz ? BUZZ : 0) | (beep ? BEEP : 0) | (blink ? BLINK : 0));
-                    proto.setTimestamp(eventTimeMs);
-                    proto.setPackageName(mKey.mPackageName);
-                    proto.addTaggedData(MetricsEvent.NOTIFICATION_ID, mKey.mId);
-                    proto.addTaggedData(MetricsEvent.NOTIFICATION_TAG, mKey.mTag);
-                    filltimes(proto);
-                    logger.addEvent(proto);
-                } else {
-                    if (debug) {
-                        Log.e(TAG, "unable to parse key: " + keyString);
-                    }
-                }
-            } catch (ClassCastException e) {
-                if (debug) {
-                    Log.e(TAG, "unexpected operand type: ", e);
-                }
-                return;
-            }
-        } else if (debug) {
-            Log.w(TAG, "wrong number of operands: " + operands.length);
-        }
-    }
-}
diff --git a/core/java/com/android/internal/logging/legacy/NotificationCanceledParser.java b/core/java/com/android/internal/logging/legacy/NotificationCanceledParser.java
deleted file mode 100644
index 80eb004..0000000
--- a/core/java/com/android/internal/logging/legacy/NotificationCanceledParser.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import android.util.Log;
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-/**
- * Parse the Android notification cancellation event logs.
- * @hide
- */
-public class NotificationCanceledParser extends TagParser {
-    private static final String TAG = "NotificationCanceled";
-    private static final int EVENTLOG_TAG = 27530;
-
-    // from com.android.server.notification.NotificationManagerService
-    static final int REASON_DELEGATE_CLICK = 1;
-    static final int REASON_DELEGATE_CANCEL = 2;
-    static final int REASON_DELEGATE_CANCEL_ALL = 3;
-    static final int REASON_PACKAGE_BANNED = 7;
-    static final int REASON_LISTENER_CANCEL = 10;
-    static final int REASON_LISTENER_CANCEL_ALL = 11;
-
-    private final NotificationKey mKey;
-
-    public NotificationCanceledParser() {
-        mKey = new NotificationKey();
-    }
-
-    @Override
-    public int getTag() {
-        return EVENTLOG_TAG;
-    }
-
-    @Override
-    public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
-        final boolean debug = Util.debug();
-        if (operands.length > 1) {
-            try {
-                final String keyString = (String) operands[0];
-                final int reason = (Integer) operands[1];
-                parseTimes(operands, 2);
-
-                // handle old style log
-                // TODO: delete once M is launched
-                if (operands.length < 5) {
-                    mSinceVisibleMillis = mSinceUpdateMillis;
-                    mSinceUpdateMillis = 0;
-                }
-
-                boolean intentional = true;
-                switch (reason) {
-                    case REASON_DELEGATE_CANCEL:
-                    case REASON_DELEGATE_CANCEL_ALL:
-                    case REASON_LISTENER_CANCEL:
-                    case REASON_LISTENER_CANCEL_ALL:
-                    case REASON_DELEGATE_CLICK:
-                    case REASON_PACKAGE_BANNED:
-                        break;
-                    default:
-                        intentional = false;
-                }
-
-                if (mKey.parse(keyString)) {
-                    if (intentional) {
-                        LogMaker proto = logger.obtain();
-                        proto.setCategory(MetricsEvent.NOTIFICATION_ITEM);
-                        proto.setType(MetricsEvent.TYPE_DISMISS);
-                        proto.setSubtype(reason);
-                        proto.setTimestamp(eventTimeMs);
-                        proto.setPackageName(mKey.mPackageName);
-                        proto.addTaggedData(MetricsEvent.NOTIFICATION_ID, mKey.mId);
-                        proto.addTaggedData(MetricsEvent.NOTIFICATION_TAG, mKey.mTag);
-                        filltimes(proto);
-                        logger.addEvent(proto);
-                    }
-                } else if (debug) {
-                    Log.e(TAG, "unable to parse key: " + keyString);
-                }
-            } catch (ClassCastException e) {
-                if (debug) {
-                    Log.e(TAG, "unexpected operand type: ", e);
-                }
-            }
-        }
-    }
-}
diff --git a/core/java/com/android/internal/logging/legacy/NotificationClickedParser.java b/core/java/com/android/internal/logging/legacy/NotificationClickedParser.java
deleted file mode 100644
index eee4701..0000000
--- a/core/java/com/android/internal/logging/legacy/NotificationClickedParser.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import android.util.Log;
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-/**
- * Parse the Android notification interaction event logs.
- * @hide
- */
-public class NotificationClickedParser extends TagParser {
-    private static final String TAG = "NotificationClicked";
-    private static final int EVENTLOG_TAG = 27520;
-
-    private final NotificationKey mKey;
-
-    public NotificationClickedParser() {
-        mKey = new NotificationKey();
-    }
-
-    @Override
-    public int getTag() {
-        return EVENTLOG_TAG;
-    }
-
-    @Override
-    public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
-        final boolean debug = Util.debug();
-        if (operands.length > 0) {
-            try {
-                if (mKey.parse((String) operands[0])) {
-                    parseTimes(operands, 1);
-                    LogMaker proto = logger.obtain();
-                    proto.setCategory(MetricsEvent.NOTIFICATION_ITEM);
-                    proto.setType(MetricsEvent.TYPE_ACTION);
-                    proto.setTimestamp(eventTimeMs);
-                    proto.setPackageName(mKey.mPackageName);
-                    proto.addTaggedData(MetricsEvent.NOTIFICATION_ID, mKey.mId);
-                    proto.addTaggedData(MetricsEvent.NOTIFICATION_TAG, mKey.mTag);
-                    filltimes(proto);
-                    logger.addEvent(proto);
-                } else if (debug) {
-                    Log.e(TAG, "unable to parse key.");
-                }
-            } catch (ClassCastException e) {
-                if (debug) {
-                    Log.e(TAG, "unexpected operand type: ", e);
-                }
-            }
-        } else if (debug) {
-            Log.w(TAG, "wrong number of operands: " + operands.length);
-        }
-    }
-}
diff --git a/core/java/com/android/internal/logging/legacy/NotificationExpansionParser.java b/core/java/com/android/internal/logging/legacy/NotificationExpansionParser.java
deleted file mode 100644
index 84cd999..0000000
--- a/core/java/com/android/internal/logging/legacy/NotificationExpansionParser.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import android.util.Log;
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-/**
- * Parse the Android notification expansion event logs.
- * @hide
- */
-public class NotificationExpansionParser extends TagParser {
-    private static final String TAG = "NotificationExpansion";
-    private static final int EVENTLOG_TAG = 27511;
-
-    private final NotificationKey mKey;
-
-    public NotificationExpansionParser() {
-        mKey = new NotificationKey();
-    }
-
-    @Override
-    public int getTag() {
-        return EVENTLOG_TAG;
-    }
-
-    @Override
-    public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
-        final boolean debug = Util.debug();
-        if (operands.length > 2) {
-            try {
-                if (mKey.parse((String) operands[0])) {
-                    boolean byUser = ((Integer) operands[1]) == 1;
-                    boolean expanded = ((Integer) operands[2]) == 1;
-                    parseTimes(operands, 3);
-
-                    if (!byUser || !expanded) {
-                        return;
-                    }
-                    LogMaker proto = logger.obtain();
-                    proto.setCategory(MetricsEvent.NOTIFICATION_ITEM);
-                    proto.setType(MetricsEvent.TYPE_DETAIL);
-                    proto.setTimestamp(eventTimeMs);
-                    proto.setPackageName(mKey.mPackageName);
-                    proto.addTaggedData(MetricsEvent.NOTIFICATION_ID, mKey.mId);
-                    proto.addTaggedData(MetricsEvent.NOTIFICATION_TAG, mKey.mTag);
-                    filltimes(proto);
-                    logger.addEvent(proto);
-                } else if (debug) {
-                    Log.e(TAG, "unable to parse key.");
-                }
-            } catch (ClassCastException e) {
-                if (debug) {
-                    Log.e(TAG, "unexpected operand type: ", e);
-                }
-            }
-        } else if (debug) {
-            Log.w(TAG, "wrong number of operands: " + operands.length);
-        }
-    }
-}
diff --git a/core/java/com/android/internal/logging/legacy/NotificationKey.java b/core/java/com/android/internal/logging/legacy/NotificationKey.java
deleted file mode 100644
index f8cac34..0000000
--- a/core/java/com/android/internal/logging/legacy/NotificationKey.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import android.util.Log;
-
-/**
- * Parse Android notification keys
- * @hide
- */
-public class NotificationKey {
-
-    private static final String TAG = "NotificationKey";
-
-    public int mUser;
-    public String mPackageName;
-    public int mId;
-    public String mTag;
-    public int mUid;
-
-    public boolean parse(String key) {
-        if (key == null) {
-            return false;
-        }
-        boolean debug = Util.debug();
-        String[] parts = key.split("\\|");
-        if (parts.length == 5) {
-            try {
-                mUser = Integer.valueOf(parts[0]);
-                mPackageName = parts[1];
-                mId = Integer.valueOf(parts[2]);
-                mTag = parts[3].equals("null") ? "" : parts[3];
-                mUid = Integer.valueOf(parts[4]);
-                return true;
-            } catch (NumberFormatException e) {
-                if (debug) {
-                    Log.w(TAG, "could not parse notification key.", e);
-                }
-                return false;
-            }
-        }
-        if (debug) {
-            Log.w(TAG, "wrong number of parts in notification key: " + key);
-        }
-        return false;
-    }
-}
diff --git a/core/java/com/android/internal/logging/legacy/NotificationPanelHiddenParser.java b/core/java/com/android/internal/logging/legacy/NotificationPanelHiddenParser.java
deleted file mode 100644
index a064a2e..0000000
--- a/core/java/com/android/internal/logging/legacy/NotificationPanelHiddenParser.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-/**
- * Parse the Android notification panel visibility event logs.
- * @hide
- */
-public class NotificationPanelHiddenParser extends TagParser {
-    private static final String TAG = "NotificationPanelHidden";
-    private static final int EVENTLOG_TAG = 27501;
-
-    @Override
-    public int getTag() {
-        return EVENTLOG_TAG;
-    }
-
-    @Override
-    public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
-        LogMaker proto = logger.obtain();
-        proto.setCategory(MetricsEvent.NOTIFICATION_PANEL);
-        proto.setType(MetricsEvent.TYPE_CLOSE);
-        proto.setTimestamp(eventTimeMs);
-        logger.addEvent(proto);
-    }
-}
diff --git a/core/java/com/android/internal/logging/legacy/NotificationPanelRevealedParser.java b/core/java/com/android/internal/logging/legacy/NotificationPanelRevealedParser.java
deleted file mode 100644
index 4d19564..0000000
--- a/core/java/com/android/internal/logging/legacy/NotificationPanelRevealedParser.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import android.util.Log;
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-/**
- * Parse the Android notification panel visibility event logs.
- * @hide
- */
-public class NotificationPanelRevealedParser extends TagParser {
-    private static final String TAG = "NotificationPanelRevea";
-    private static final int EVENTLOG_TAG = 27500;
-
-    @Override
-    public int getTag() {
-        return EVENTLOG_TAG;
-    }
-
-    @Override
-    public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
-        final boolean debug = Util.debug();
-        if (operands.length >= 1) {
-            try {
-                int load = ((Integer) operands[0]).intValue();
-                //logger.incrementBy(TronCounters.TRON_NOTIFICATION_LOAD, load);
-            } catch (ClassCastException e) {
-                if (debug) {
-                    Log.e(TAG, "unexpected operand type: ", e);
-                }
-            }
-        }
-
-        LogMaker proto = logger.obtain();
-        proto.setCategory(MetricsEvent.NOTIFICATION_PANEL);
-        proto.setType(MetricsEvent.TYPE_OPEN);
-        proto.setTimestamp(eventTimeMs);
-        logger.addEvent(proto);
-    }
-}
diff --git a/core/java/com/android/internal/logging/legacy/NotificationVisibilityParser.java b/core/java/com/android/internal/logging/legacy/NotificationVisibilityParser.java
deleted file mode 100644
index 2d2cd909..0000000
--- a/core/java/com/android/internal/logging/legacy/NotificationVisibilityParser.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import android.util.Log;
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-/**
- * Parse the new Android notification visibility event logs.
- * @hide
- */
-public class NotificationVisibilityParser extends TagParser {
-    private static final String TAG = "NotificationVisibility";
-    private static final int EVENTLOG_TAG = 27531;
-
-    private final NotificationKey mKey;
-
-    public NotificationVisibilityParser() {
-        mKey = new NotificationKey();
-    }
-
-    @Override
-    public int getTag() {
-        return EVENTLOG_TAG;
-    }
-
-    @Override
-    public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
-        final boolean debug = Util.debug();
-        if (operands.length > 1) {
-            try {
-                final String keyString = (String) operands[0];
-                final boolean visible = ((Integer) operands[1]) == 1;
-                parseTimes(operands, 2);
-                int index = 0;
-                if (operands.length > 5 && operands[5] instanceof Integer) {
-                    index = (Integer) operands[5];
-                }
-
-                if (mKey.parse(keyString)) {
-                    LogMaker proto = logger.obtain();
-                    proto.setCategory(MetricsEvent.NOTIFICATION_ITEM);
-                    proto.setType(visible ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE);
-                    proto.setTimestamp(eventTimeMs);
-                    proto.setPackageName(mKey.mPackageName);
-                    proto.addTaggedData(MetricsEvent.NOTIFICATION_ID, mKey.mId);
-                    proto.addTaggedData(MetricsEvent.NOTIFICATION_TAG, mKey.mTag);
-                    proto.addTaggedData(MetricsEvent.NOTIFICATION_SHADE_INDEX, index);
-                    filltimes(proto);
-                    logger.addEvent(proto);
-                } else {
-                    if (debug) {
-                        Log.e(TAG, "unable to parse key: " + keyString);
-                    }
-                }
-            } catch (ClassCastException e) {
-                if (debug) {
-                    Log.e(TAG, "unexpected operand type: ", e);
-                }
-                return;
-            }
-        } else if (debug) {
-            Log.w(TAG, "wrong number of operands: " + operands.length);
-        }
-    }
-}
diff --git a/core/java/com/android/internal/logging/legacy/SysuiActionParser.java b/core/java/com/android/internal/logging/legacy/SysuiActionParser.java
deleted file mode 100644
index 1148ee5..0000000
--- a/core/java/com/android/internal/logging/legacy/SysuiActionParser.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import android.util.Log;
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-/**
- * Parse the Android framework sysui action logs.
- * @hide
- */
-public class SysuiActionParser extends TagParser {
-    private static final String TAG = "SysuiActionParser";
-    private static final int EVENTLOG_TAG = 524288;
-
-    @Override
-    public int getTag() {
-        return EVENTLOG_TAG;
-    }
-
-    @Override
-    public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
-        final boolean debug = Util.debug();
-        try {
-            String packageName = null;
-            int subType = -1;
-            boolean hasSubType = false;
-            if (operands.length > 1) {
-                String arg = (String) operands[1];
-                if (arg.equals("true")) {
-                    hasSubType = true;
-                    subType = 1;
-                } else if (arg.equals("false")) {
-                    hasSubType = true;
-                    subType = 0;
-                } else if (arg.matches("^-?\\d+$")) {
-                    try {
-                        subType = Integer.valueOf(arg);
-                        hasSubType = true;
-                    } catch (NumberFormatException e) {
-                    }
-                } else {
-                    packageName = arg;
-                }
-            }
-            if (operands.length > 0) {
-                int category = ((Integer) operands[0]).intValue();
-                LogMaker proto = logger.obtain();
-                proto.setCategory(category);
-                proto.setType(MetricsEvent.TYPE_ACTION);
-                proto.setTimestamp(eventTimeMs);
-                if (packageName != null) {
-                    proto.setPackageName(packageName);
-                }
-                if (hasSubType) {
-                    proto.setSubtype(subType);
-                }
-                logger.addEvent(proto);
-            }
-        } catch (ClassCastException e) {
-            if (debug) {
-                Log.e(TAG, "unexpected operand type: ", e);
-            }
-        }
-    }
-}
diff --git a/core/java/com/android/internal/logging/legacy/SysuiViewVisibilityParser.java b/core/java/com/android/internal/logging/legacy/SysuiViewVisibilityParser.java
deleted file mode 100644
index 1223b8d..0000000
--- a/core/java/com/android/internal/logging/legacy/SysuiViewVisibilityParser.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import android.util.Log;
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-/**
- * Parse the Android framework sysui view visibility logs.
- * @hide
- */
-public class SysuiViewVisibilityParser extends TagParser {
-    private static final String TAG = "SysuiViewVisibility";
-    private static final int EVENTLOG_TAG = 524287;
-
-    @Override
-    public int getTag() {
-        return EVENTLOG_TAG;
-    }
-
-    @Override
-    public void parseEvent(TronLogger logger, long eventTimeMs, Object[] operands) {
-        final boolean debug = Util.debug();
-        if (operands.length >= 2) {
-            try {
-                int category = ((Integer) operands[0]).intValue();
-                boolean visibility = ((Integer) operands[1]).intValue() != 0;
-
-                LogMaker proto = logger.obtain();
-                proto.setCategory(category);
-                proto.setType(visibility ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE);
-                proto.setTimestamp(eventTimeMs);
-                logger.addEvent(proto);
-            } catch (ClassCastException e) {
-                if (debug) {
-                    Log.e(TAG, "unexpected operand type: ", e);
-                }
-            }
-        } else if (debug) {
-            Log.w(TAG, "wrong number of operands: " + operands.length);
-        }
-    }
-}
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index e1e0a21..59416dd 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -33,7 +33,7 @@
     */
 
     /** enable debugging over JDWP */
-    public static final int DEBUG_ENABLE_DEBUGGER   = 1;
+    public static final int DEBUG_ENABLE_JDWP   = 1;
     /** enable JNI checks */
     public static final int DEBUG_ENABLE_CHECKJNI   = 1 << 1;
     /** enable Java programming language "assert" statements */
@@ -46,8 +46,10 @@
     public static final int DEBUG_GENERATE_DEBUG_INFO = 1 << 5;
     /** Always use JIT-ed code. */
     public static final int DEBUG_ALWAYS_JIT = 1 << 6;
-    /** Make the code debuggable with turning off some optimizations. */
+    /** Make the code native debuggable by turning off some optimizations. */
     public static final int DEBUG_NATIVE_DEBUGGABLE = 1 << 7;
+    /** Make the code Java debuggable by turning off some optimizations. */
+    public static final int DEBUG_JAVA_DEBUGGABLE = 1 << 8;
 
     /** No external storage should be mounted. */
     public static final int MOUNT_EXTERNAL_NONE = 0;
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 83e3cff..8fe374c 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -342,8 +342,9 @@
         int[] gids;
 
         /**
-         * From --enable-debugger, --enable-checkjni, --enable-assert,
-         * --enable-safemode, --generate-debug-info and --enable-jni-logging.
+         * From --enable-jdwp, --enable-checkjni, --enable-assert,
+         * --enable-safemode, --generate-debug-info, --enable-jni-logging,
+         * --java-debuggable, and --native-debuggable.
          */
         int debugFlags;
 
@@ -453,8 +454,8 @@
                     targetSdkVersionSpecified = true;
                     targetSdkVersion = Integer.parseInt(
                             arg.substring(arg.indexOf('=') + 1));
-                } else if (arg.equals("--enable-debugger")) {
-                    debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
+                } else if (arg.equals("--enable-jdwp")) {
+                    debugFlags |= Zygote.DEBUG_ENABLE_JDWP;
                 } else if (arg.equals("--enable-safemode")) {
                     debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
                 } else if (arg.equals("--enable-checkjni")) {
@@ -465,6 +466,8 @@
                     debugFlags |= Zygote.DEBUG_ALWAYS_JIT;
                 } else if (arg.equals("--native-debuggable")) {
                     debugFlags |= Zygote.DEBUG_NATIVE_DEBUGGABLE;
+                } else if (arg.equals("--java-debuggable")) {
+                    debugFlags |= Zygote.DEBUG_JAVA_DEBUGGABLE;
                 } else if (arg.equals("--enable-jni-logging")) {
                     debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
                 } else if (arg.equals("--enable-assert")) {
@@ -676,14 +679,14 @@
      * Applies debugger system properties to the zygote arguments.
      *
      * If "ro.debuggable" is "1", all apps are debuggable. Otherwise,
-     * the debugger state is specified via the "--enable-debugger" flag
+     * the debugger state is specified via the "--enable-jdwp" flag
      * in the spawn request.
      *
      * @param args non-null; zygote spawner args
      */
     public static void applyDebuggerSystemProperty(Arguments args) {
         if (RoSystemProperties.DEBUGGABLE) {
-            args.debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
+            args.debugFlags |= Zygote.DEBUG_ENABLE_JDWP;
         }
     }
 
@@ -705,7 +708,7 @@
         int peerUid = peer.getUid();
 
         if (args.invokeWith != null && peerUid != 0 &&
-            (args.debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) == 0) {
+            (args.debugFlags & Zygote.DEBUG_ENABLE_JDWP) == 0) {
             throw new ZygoteSecurityException("Peer is permitted to specify an"
                     + "explicit invoke-with wrapper command only for debuggable"
                     + "applications.");
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 789e9d4..7ff115b 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -2243,6 +2243,14 @@
     }
 
     @Override
+    public void dispatchPointerCaptureChanged(boolean hasCapture) {
+        super.dispatchPointerCaptureChanged(hasCapture);
+        if (!mWindow.isDestroyed() && mWindow.getCallback() != null) {
+            mWindow.getCallback().onPointerCaptureChanged(hasCapture);
+        }
+    }
+
+    @Override
     public String toString() {
         return "DecorView@" + Integer.toHexString(this.hashCode()) + "["
                 + getTitleSuffix(mWindow.getAttributes()) + "]";
diff --git a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
index cf14471..11e7102 100644
--- a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
@@ -53,6 +53,11 @@
      */
     private static final int SNAP_ONLY_1_1 = 2;
 
+    /**
+     * 1 snap target: minimized height, (1 - minimized height)
+     */
+    private static final int SNAP_MODE_MINIMIZED = 3;
+
     private final float mMinFlingVelocityPxPerSecond;
     private final float mMinDismissVelocityPxPerSecond;
     private final int mDisplayWidth;
@@ -62,6 +67,7 @@
     private final Rect mInsets = new Rect();
     private final int mSnapMode;
     private final int mMinimalSizeResizableTask;
+    private final int mTaskHeightInMinimizedMode;
     private final float mFixedRatio;
     private boolean mIsHorizontalDivision;
 
@@ -93,6 +99,11 @@
 
     public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize,
             boolean isHorizontalDivision, Rect insets) {
+        this(res, displayWidth, displayHeight, dividerSize, isHorizontalDivision, insets, false);
+    }
+
+    public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize,
+            boolean isHorizontalDivision, Rect insets, boolean isMinimizedMode) {
         mMinFlingVelocityPxPerSecond =
                 MIN_FLING_VELOCITY_DP_PER_SECOND * res.getDisplayMetrics().density;
         mMinDismissVelocityPxPerSecond =
@@ -102,12 +113,14 @@
         mDisplayHeight = displayHeight;
         mIsHorizontalDivision = isHorizontalDivision;
         mInsets.set(insets);
-        mSnapMode = res.getInteger(
-                com.android.internal.R.integer.config_dockedStackDividerSnapMode);
+        mSnapMode = isMinimizedMode ? SNAP_MODE_MINIMIZED :
+                res.getInteger(com.android.internal.R.integer.config_dockedStackDividerSnapMode);
         mFixedRatio = res.getFraction(
                 com.android.internal.R.fraction.docked_stack_divider_fixed_ratio, 1, 1);
         mMinimalSizeResizableTask = res.getDimensionPixelSize(
                 com.android.internal.R.dimen.default_minimal_size_resizable_task);
+        mTaskHeightInMinimizedMode = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.task_height_of_minimized_mode);
         calculateTargets(isHorizontalDivision);
         mFirstSplitTarget = mTargets.get(1);
         mLastSplitTarget = mTargets.get(mTargets.size() - 2);
@@ -246,6 +259,7 @@
         int dividerMax = isHorizontalDivision
                 ? mDisplayHeight
                 : mDisplayWidth;
+        int navBarSize = isHorizontalDivision ? mInsets.bottom : mInsets.right;
         mTargets.add(new SnapTarget(-mDividerSize, -mDividerSize, SnapTarget.FLAG_DISMISS_START,
                 0.35f));
         switch (mSnapMode) {
@@ -258,8 +272,10 @@
             case SNAP_ONLY_1_1:
                 addMiddleTarget(isHorizontalDivision);
                 break;
+            case SNAP_MODE_MINIMIZED:
+                addMinimizedTarget(isHorizontalDivision);
+                break;
         }
-        int navBarSize = isHorizontalDivision ? mInsets.bottom : mInsets.right;
         mTargets.add(new SnapTarget(dividerMax - navBarSize, dividerMax,
                 SnapTarget.FLAG_DISMISS_END, 0.35f));
     }
@@ -315,6 +331,12 @@
         mTargets.add(new SnapTarget(position, position, SnapTarget.FLAG_NONE));
     }
 
+    private void addMinimizedTarget(boolean isHorizontalDivision) {
+        int position = mTaskHeightInMinimizedMode;
+        position += isHorizontalDivision ? mInsets.top : mInsets.left;
+        mTargets.add(new SnapTarget(position, position, SnapTarget.FLAG_NONE));
+    }
+
     public SnapTarget getMiddleTarget() {
         return mMiddleTarget;
     }
diff --git a/core/java/com/android/internal/policy/PipSnapAlgorithm.java b/core/java/com/android/internal/policy/PipSnapAlgorithm.java
index 6d13743..ec92aa9 100644
--- a/core/java/com/android/internal/policy/PipSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/PipSnapAlgorithm.java
@@ -39,20 +39,27 @@
     private static final int SNAP_MODE_CORNERS_AND_SIDES = 1;
     // Allows snapping to anywhere along the edge of the screen
     private static final int SNAP_MODE_EDGE = 2;
+    // Allows snapping to four corners on a fling towards a corner or slow move near a corner
+    // snaps anywhere along the edge of screen otherwise
+    private static final int SNAP_MODE_CORNERS_AND_EDGES = 3;
 
     // The friction multiplier to control how slippery the PIP is when flung
     private static final float SCROLL_FRICTION_MULTIPLIER = 8f;
 
+    // Threshold to magnet to a corner
+    private static final float CORNER_MAGNET_THRESHOLD = 0.3f;
+
     private final Context mContext;
 
     private final ArrayList<Integer> mSnapGravities = new ArrayList<>();
-    private final int mDefaultSnapMode = SNAP_MODE_CORNERS_ONLY;
+    private final int mDefaultSnapMode = SNAP_MODE_CORNERS_AND_EDGES;
     private int mSnapMode = mDefaultSnapMode;
 
     private Scroller mScroller;
     private int mOrientation = Configuration.ORIENTATION_UNDEFINED;
 
     private final int mMinimizedVisibleSize;
+    private boolean mIsMinimized;
 
     public PipSnapAlgorithm(Context context) {
         mContext = context;
@@ -70,6 +77,13 @@
     }
 
     /**
+     * Sets the PIP's minimized state.
+     */
+    public void setMinimized(boolean isMinimized) {
+        mIsMinimized = isMinimized;
+    }
+
+    /**
      * Enables snapping to the closest edge.
      */
     public void setSnapToEdge(boolean snapToEdge) {
@@ -107,7 +121,24 @@
                 movementBounds.right + stackBounds.width(),
                 movementBounds.bottom + stackBounds.height());
         final Rect newBounds = new Rect(stackBounds);
-        if (mSnapMode == SNAP_MODE_EDGE) {
+        if (mSnapMode == SNAP_MODE_CORNERS_AND_EDGES) {
+            final Rect tmpBounds = new Rect();
+            final Point[] snapTargets = new Point[mSnapGravities.size()];
+            for (int i = 0; i < mSnapGravities.size(); i++) {
+                Gravity.apply(mSnapGravities.get(i), stackBounds.width(), stackBounds.height(),
+                        pipBounds, 0, 0, tmpBounds);
+                snapTargets[i] = new Point(tmpBounds.left, tmpBounds.top);
+            }
+            Point snapTarget = findClosestPoint(stackBounds.left, stackBounds.top, snapTargets);
+            float distance = distanceToPoint(snapTarget, stackBounds.left, stackBounds.top);
+            final float thresh = stackBounds.width() * CORNER_MAGNET_THRESHOLD;
+            if (distance < thresh) {
+                newBounds.offsetTo(snapTarget.x, snapTarget.y);
+            } else {
+                // Otherwise we snap to the edge
+                snapRectToClosestEdge(stackBounds, movementBounds, newBounds);
+            }
+        } else if (mSnapMode == SNAP_MODE_EDGE) {
             // Find the closest edge to the given stack bounds and snap to it
             snapRectToClosestEdge(stackBounds, movementBounds, newBounds);
         } else {
@@ -228,8 +259,7 @@
         final int boundedTop = Math.max(movementBounds.top, Math.min(movementBounds.bottom,
                 stackBounds.top));
         boundsOut.set(stackBounds);
-        if (stackBounds.left < movementBounds.left ||
-                stackBounds.left > movementBounds.right) {
+        if (mIsMinimized) {
             boundsOut.offsetTo(boundedLeft, boundsOut.top);
             return;
         }
@@ -273,6 +303,7 @@
                 }
                 // Fall through
             case SNAP_MODE_CORNERS_ONLY:
+            case SNAP_MODE_CORNERS_AND_EDGES:
                 mSnapGravities.add(Gravity.TOP | Gravity.LEFT);
                 mSnapGravities.add(Gravity.TOP | Gravity.RIGHT);
                 mSnapGravities.add(Gravity.BOTTOM | Gravity.LEFT);
diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java
index 087383d..0fe580a 100644
--- a/core/java/com/android/internal/util/NotificationColorUtil.java
+++ b/core/java/com/android/internal/util/NotificationColorUtil.java
@@ -33,6 +33,8 @@
 import android.graphics.drawable.VectorDrawable;
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
+import android.text.style.CharacterStyle;
+import android.text.style.ForegroundColorSpan;
 import android.text.style.TextAppearanceSpan;
 import android.util.Log;
 import android.util.Pair;
@@ -184,8 +186,24 @@
             SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString());
             for (Object span : spans) {
                 Object resultSpan = span;
-                if (span instanceof TextAppearanceSpan) {
-                    resultSpan = processTextAppearanceSpan((TextAppearanceSpan) span);
+                if (resultSpan instanceof CharacterStyle) {
+                    resultSpan = ((CharacterStyle) span).getUnderlying();
+                }
+                if (resultSpan instanceof TextAppearanceSpan) {
+                    TextAppearanceSpan processedSpan = processTextAppearanceSpan(
+                            (TextAppearanceSpan) span);
+                    if (processedSpan != resultSpan) {
+                        resultSpan = processedSpan;
+                    } else {
+                        // we need to still take the orgininal for wrapped spans
+                        resultSpan = span;
+                    }
+                } else if (resultSpan instanceof ForegroundColorSpan) {
+                    ForegroundColorSpan originalSpan = (ForegroundColorSpan) resultSpan;
+                    int foregroundColor = originalSpan.getForegroundColor();
+                    resultSpan = new ForegroundColorSpan(processColor(foregroundColor));
+                } else {
+                    resultSpan = span;
                 }
                 builder.setSpan(resultSpan, ss.getSpanStart(span), ss.getSpanEnd(span),
                         ss.getSpanFlags(span));
@@ -416,6 +434,48 @@
         return color;
     }
 
+    public static int resolvePrimaryColor(Context context, int backgroundColor) {
+        boolean useDark = shouldUseDark(backgroundColor);
+        if (useDark) {
+            return context.getColor(
+                    com.android.internal.R.color.notification_primary_text_color_light);
+        } else {
+            return context.getColor(
+                    com.android.internal.R.color.notification_primary_text_color_dark);
+        }
+    }
+
+    public static int resolveSecondaryColor(Context context, int backgroundColor) {
+        boolean useDark = shouldUseDark(backgroundColor);
+        if (useDark) {
+            return context.getColor(
+                    com.android.internal.R.color.notification_secondary_text_color_light);
+        } else {
+            return context.getColor(
+                    com.android.internal.R.color.notification_secondary_text_color_dark);
+        }
+    }
+
+    public static int resolveActionBarColor(int backgroundColor) {
+        boolean useDark = shouldUseDark(backgroundColor);
+        final double[] result = ColorUtilsFromCompat.getTempDouble3Array();
+        ColorUtilsFromCompat.colorToLAB(backgroundColor, result);
+        if (useDark && result[0] < 97 || !useDark && result[0] < 4) {
+            result[0] = Math.min(100, result[0] + 7);
+        } else {
+            result[0] = Math.max(0, result[0] - 7);
+        }
+        return ColorUtilsFromCompat.LABToColor(result[0], result[1], result[2]);
+    }
+
+    private static boolean shouldUseDark(int backgroundColor) {
+        boolean useDark = backgroundColor == Notification.COLOR_DEFAULT;
+        if (!useDark) {
+            useDark = ColorUtilsFromCompat.calculateLuminance(backgroundColor) > 0.5;
+        }
+        return useDark;
+    }
+
     /**
      * Framework copy of functions needed from android.support.v4.graphics.ColorUtils.
      */
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index c9c8292..dd91d2f 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -122,4 +122,8 @@
     @Override
     public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {
     }
+
+    @Override
+    public void dispatchPointerCaptureChanged(boolean hasCapture) {
+    }
 }
diff --git a/core/jni/android_hardware_Radio.cpp b/core/jni/android_hardware_Radio.cpp
index 397e67b..b6b1ac7 100644
--- a/core/jni/android_hardware_Radio.cpp
+++ b/core/jni/android_hardware_Radio.cpp
@@ -23,7 +23,7 @@
 #include "JNIHelp.h"
 #include "core_jni_helpers.h"
 #include <system/radio.h>
-#include <system/radio_metadata.h>
+#include <system/RadioMetadataWrapper.h>
 #include <radio/RadioCallback.h>
 #include <radio/Radio.h>
 #include <utils/RefBase.h>
@@ -752,7 +752,7 @@
     }
 
     struct radio_program_info nInfo;
-    radio_metadata_allocate(&nInfo.metadata, 0, 0);
+    RadioMetadataWrapper metadataWrapper(&nInfo.metadata);
     jobject jInfo = NULL;
     int jStatus;
 
@@ -770,7 +770,6 @@
     if (jInfo != NULL) {
         env->DeleteLocalRef(jInfo);
     }
-    radio_metadata_deallocate(nInfo.metadata);
     return jStatus;
 }
 
diff --git a/core/jni/android_hardware_SoundTrigger.cpp b/core/jni/android_hardware_SoundTrigger.cpp
index 793d132..0c7f5a1 100644
--- a/core/jni/android_hardware_SoundTrigger.cpp
+++ b/core/jni/android_hardware_SoundTrigger.cpp
@@ -509,7 +509,7 @@
     sp<MemoryDealer> memoryDealer;
     sp<IMemory> memory;
     size_t size;
-    sound_model_handle_t handle;
+    sound_model_handle_t handle = 0;
     jobject jUuid;
     jstring jUuidString;
     const char *nUuidString;
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 86c4df7..b2c8168 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -972,6 +972,18 @@
 }
 
 // ----------------------------------------------------------------------------
+static jint android_media_AudioTrack_get_flags(JNIEnv *env,  jobject thiz) {
+    sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
+
+    if (lpTrack == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException",
+            "Unable to retrieve AudioTrack pointer for getFlags()");
+        return (jint)AUDIO_JAVA_ERROR;
+    }
+    return (jint)lpTrack->getFlags();
+}
+
+// ----------------------------------------------------------------------------
 static jint android_media_AudioTrack_get_timestamp(JNIEnv *env,  jobject thiz, jlongArray jTimestamp) {
     sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
 
@@ -1212,6 +1224,7 @@
     {"native_get_position",  "()I",      (void *)android_media_AudioTrack_get_position},
     {"native_get_latency",   "()I",      (void *)android_media_AudioTrack_get_latency},
     {"native_get_underrun_count", "()I",      (void *)android_media_AudioTrack_get_underrun_count},
+    {"native_get_flags",     "()I",      (void *)android_media_AudioTrack_get_flags},
     {"native_get_timestamp", "([J)I",    (void *)android_media_AudioTrack_get_timestamp},
     {"native_set_loop",      "(III)I",   (void *)android_media_AudioTrack_set_loop},
     {"native_reload_static", "()I",      (void *)android_media_AudioTrack_reload},
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index d382f24..723dce6 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -681,7 +681,7 @@
                                                           jint smallestScreenWidthDp,
                                                           jint screenWidthDp, jint screenHeightDp,
                                                           jint screenLayout, jint uiMode,
-                                                          jint sdkVersion)
+                                                          jint colorMode, jint sdkVersion)
 {
     AssetManager* am = assetManagerForJavaObject(env, clazz);
     if (am == NULL) {
@@ -712,6 +712,7 @@
     config.screenHeightDp = (uint16_t)screenHeightDp;
     config.screenLayout = (uint8_t)screenLayout;
     config.uiMode = (uint8_t)uiMode;
+    config.colorMode = (uint8_t)colorMode;
     config.sdkVersion = (uint16_t)sdkVersion;
     config.minorVersion = 0;
 
@@ -1691,7 +1692,7 @@
     { "getSizeConfigurations", "()[Landroid/content/res/Configuration;",
         (void*) android_content_AssetManager_getSizeConfigurations },
     // @FastNative
-    { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
+    { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIIII)V",
         (void*) android_content_AssetManager_setConfiguration },
     // @FastNative
     { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index d75d5c1..f221392 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -43,57 +43,6 @@
         ? (reinterpret_cast<RenderNode*>(renderNodePtr)->setPropertyFieldsDirty(dirtyFlag), true) \
         : false)
 
-static JNIEnv* getenv(JavaVM* vm) {
-    JNIEnv* env;
-    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
-        LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
-    }
-    return env;
-}
-
-static jfieldID gRenderNode_validFieldID;
-
-class RenderNodeContext : public VirtualLightRefBase {
-public:
-    RenderNodeContext(JNIEnv* env, jobject jobjRef) {
-        env->GetJavaVM(&mVm);
-        // This holds a weak ref because otherwise there's a cyclic global ref
-        // with this holding a strong global ref to the view which holds
-        // a strong ref to RenderNode which holds a strong ref to this.
-        mWeakRef = env->NewWeakGlobalRef(jobjRef);
-    }
-
-    virtual ~RenderNodeContext() {
-        JNIEnv* env = getenv(mVm);
-        env->DeleteWeakGlobalRef(mWeakRef);
-    }
-
-    jobject acquireLocalRef(JNIEnv* env) {
-        return env->NewLocalRef(mWeakRef);
-    }
-
-private:
-    JavaVM* mVm;
-    jweak mWeakRef;
-};
-
-// Called by ThreadedRenderer's JNI layer
-void onRenderNodeRemoved(JNIEnv* env, RenderNode* node) {
-    auto context = reinterpret_cast<RenderNodeContext*>(node->getUserContext());
-    if (!context) return;
-    jobject jnode = context->acquireLocalRef(env);
-    if (!jnode) {
-        // The owning node has been GC'd, release the context
-        node->setUserContext(nullptr);
-        return;
-    }
-
-    // Update the valid field, since native has already removed
-    // the staging DisplayList
-    env->SetBooleanField(jnode, gRenderNode_validFieldID, false);
-    env->DeleteLocalRef(jnode);
-}
-
 // ----------------------------------------------------------------------------
 // DisplayList view properties
 // ----------------------------------------------------------------------------
@@ -108,8 +57,7 @@
     return renderNode->getDebugSize();
 }
 
-static jlong android_view_RenderNode_create(JNIEnv* env, jobject thiz,
-        jstring name) {
+static jlong android_view_RenderNode_create(JNIEnv* env, jobject, jstring name) {
     RenderNode* renderNode = new RenderNode();
     renderNode->incStrong(0);
     if (name != NULL) {
@@ -117,7 +65,6 @@
         renderNode->setName(textArray);
         env->ReleaseStringUTFChars(name, textArray);
     }
-    renderNode->setUserContext(new RenderNodeContext(env, thiz));
     return reinterpret_cast<jlong>(renderNode);
 }
 
@@ -132,22 +79,13 @@
 
 static void android_view_RenderNode_setDisplayList(JNIEnv* env,
         jobject clazz, jlong renderNodePtr, jlong displayListPtr) {
-    class RemovedObserver : public TreeObserver {
-    public:
-        virtual void onMaybeRemovedFromTree(RenderNode* node) override {
-            maybeRemovedNodes.insert(sp<RenderNode>(node));
-        }
-        std::set< sp<RenderNode> > maybeRemovedNodes;
-    };
-
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     DisplayList* newData = reinterpret_cast<DisplayList*>(displayListPtr);
-    RemovedObserver observer;
-    renderNode->setStagingDisplayList(newData, &observer);
-    for (auto& node : observer.maybeRemovedNodes) {
-        if (node->hasParents()) continue;
-        onRenderNodeRemoved(env, node.get());
-    }
+    renderNode->setStagingDisplayList(newData);
+}
+
+static jboolean android_view_RenderNode_isValid(jlong renderNodePtr) {
+    return reinterpret_cast<RenderNode*>(renderNodePtr)->isValid();
 }
 
 // ----------------------------------------------------------------------------
@@ -621,6 +559,7 @@
 // ----------------------------------------------------------------------------
 // Critical JNI via @CriticalNative annotation in RenderNode.java
 // ----------------------------------------------------------------------------
+    { "nIsValid",              "(J)Z",   (void*) android_view_RenderNode_isValid },
     { "nSetLayerType",         "(JI)Z",  (void*) android_view_RenderNode_setLayerType },
     { "nSetLayerPaint",        "(JJ)Z",  (void*) android_view_RenderNode_setLayerPaint },
     { "nSetStaticMatrix",      "(JJ)Z",  (void*) android_view_RenderNode_setStaticMatrix },
@@ -691,8 +630,6 @@
             "updateWindowPosition_renderWorker", "(JIIII)V");
     gSurfaceViewPositionLostMethod = GetMethodIDOrDie(env, clazz,
             "windowPositionLost_uiRtSync", "(J)V");
-    clazz = FindClassOrDie(env, "android/view/RenderNode");
-    gRenderNode_validFieldID = GetFieldIDOrDie(env, clazz, "mValid", "Z");
     return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
 }
 
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 96e6f81..bc5f847 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -532,7 +532,7 @@
     UiFrameInfoBuilder(proxy->frameInfo())
             .setVsync(vsync, vsync)
             .addFlag(FrameInfoFlags::SurfaceCanvas);
-    proxy->syncAndDrawFrame(nullptr);
+    proxy->syncAndDrawFrame();
 }
 
 static void destroy(JNIEnv* env, jclass clazz, jlong rendererPtr) {
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index a3fef27..ab3e311 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -98,11 +98,12 @@
 // ----------------------------------------------------------------------------
 
 static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
-        jstring nameStr, jint w, jint h, jint format, jint flags) {
+        jstring nameStr, jint w, jint h, jint format, jint flags, jlong parentObject) {
     ScopedUtfChars name(env, nameStr);
     sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
+    SurfaceControl *parent = reinterpret_cast<SurfaceControl*>(parentObject);
     sp<SurfaceControl> surface = client->createSurface(
-            String8(name.c_str()), w, h, format, flags);
+            String8(name.c_str()), w, h, format, flags, parent);
     if (surface == NULL) {
         jniThrowException(env, OutOfResourcesException, NULL);
         return 0;
@@ -147,8 +148,8 @@
     }
     Rect sourceCrop = rectFromObj(env, sourceCropObj);
     if (allLayers) {
-        minLayer = 0;
-        maxLayer = -1;
+        minLayer = INT32_MIN;
+        maxLayer = INT32_MAX;
     }
     sp<GraphicBuffer> buffer;
     status_t res = ScreenshotClient::captureToBuffer(displayToken,
@@ -181,8 +182,8 @@
     std::unique_ptr<ScreenshotClient> screenshot(new ScreenshotClient());
     status_t res;
     if (allLayers) {
-        minLayer = 0;
-        maxLayer = -1;
+        minLayer = INT32_MIN;
+        maxLayer = INT32_MAX;
     }
 
     res = screenshot->update(displayToken, sourceCrop, width, height,
@@ -254,8 +255,8 @@
             Rect sourceCrop(left, top, right, bottom);
 
             if (allLayers) {
-                minLayer = 0;
-                maxLayer = -1;
+                minLayer = INT32_MIN;
+                maxLayer = INT32_MAX;
             }
             ScreenshotClient::capture(displayToken,
                     consumer->getIGraphicBufferProducer(), sourceCrop,
@@ -741,7 +742,7 @@
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod sSurfaceControlMethods[] = {
-    {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIII)J",
+    {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIIIJ)J",
             (void*)nativeCreate },
     {"nativeRelease", "(J)V",
             (void*)nativeRelease },
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index c00bcd4..d37f96a 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -71,31 +71,6 @@
     return env;
 }
 
-// TODO: Clean this up, it's a bit odd to need to call over to
-// rendernode's jni layer. Probably means RootRenderNode should be pulled
-// into HWUI with appropriate callbacks for the various JNI hooks so
-// that RenderNode's JNI layer can handle its own thing
-void onRenderNodeRemoved(JNIEnv* env, RenderNode* node);
-
-class ScopedRemovedRenderNodeObserver : public TreeObserver {
-public:
-    explicit ScopedRemovedRenderNodeObserver(JNIEnv* env) : mEnv(env) {}
-    ~ScopedRemovedRenderNodeObserver() {
-        for (auto& node : mMaybeRemovedNodes) {
-            if (node->hasParents()) continue;
-            onRenderNodeRemoved(mEnv, node.get());
-        }
-    }
-
-    virtual void onMaybeRemovedFromTree(RenderNode* node) override {
-        mMaybeRemovedNodes.insert(sp<RenderNode>(node));
-    }
-
-private:
-    JNIEnv* mEnv;
-    std::set< sp<RenderNode> > mMaybeRemovedNodes;
-};
-
 class OnFinishedEvent {
 public:
     OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
@@ -715,18 +690,16 @@
             "Mismatched size expectations, given %d expected %d",
             frameInfoSize, UI_THREAD_FRAME_INFO_SIZE);
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    ScopedRemovedRenderNodeObserver observer(env);
     env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
-    return proxy->syncAndDrawFrame(&observer);
+    return proxy->syncAndDrawFrame();
 }
 
 static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jlong rootNodePtr) {
-    ScopedRemovedRenderNodeObserver observer(env);
     RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr);
     rootRenderNode->destroy();
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    proxy->destroy(&observer);
+    proxy->destroy();
 }
 
 static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz,
@@ -758,10 +731,9 @@
 
 static void android_view_ThreadedRenderer_buildLayer(JNIEnv* env, jobject clazz,
         jlong proxyPtr, jlong nodePtr) {
-    ScopedRemovedRenderNodeObserver observer(env);
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
     RenderNode* node = reinterpret_cast<RenderNode*>(nodePtr);
-    proxy->buildLayer(node, &observer);
+    proxy->buildLayer(node);
 }
 
 static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
@@ -796,9 +768,8 @@
 
 static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
         jlong proxyPtr) {
-    ScopedRemovedRenderNodeObserver observer(env);
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    proxy->destroyHardwareResources(&observer);
+    proxy->destroyHardwareResources();
 }
 
 static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 070a2d9..5c65241 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -247,6 +247,11 @@
 
 static void DropCapabilitiesBoundingSet(JNIEnv* env) {
   for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
+    // Keep CAP_SYS_PTRACE in our bounding set so crash_dump can gain it.
+    if (i == CAP_SYS_PTRACE) {
+      continue;
+    }
+
     int rc = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
     if (rc == -1) {
       if (errno == EINVAL) {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 094e2b8..540f924 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -82,6 +82,10 @@
     <protected-broadcast android:name="android.intent.action.USER_SWITCHED" />
     <protected-broadcast android:name="android.intent.action.USER_INITIALIZE" />
     <protected-broadcast android:name="android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION" />
+    <protected-broadcast android:name="android.intent.action.OVERLAY_ADDED" />
+    <protected-broadcast android:name="android.intent.action.OVERLAY_CHANGED" />
+    <protected-broadcast android:name="android.intent.action.OVERLAY_REMOVED" />
+    <protected-broadcast android:name="android.intent.action.OVERLAY_PRIORITY_CHANGED" />
 
     <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED" />
     <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGING" />
@@ -1609,6 +1613,16 @@
     <permission android:name="android.permission.RECEIVE_STK_COMMANDS"
         android:protectionLevel="signature|privileged" />
 
+    <!-- Must be required by an ImsService to ensure that only the
+         system can bind to it.
+         <p>Protection level: signature|privileged
+         @SystemApi
+         @hide
+    -->
+    <permission android:name="android.permission.BIND_IMS_SERVICE"
+        android:protectionLevel="signature|privileged" />
+
+
     <!-- ================================== -->
     <!-- Permissions for sdcard interaction -->
     <!-- ================================== -->
@@ -2097,6 +2111,12 @@
         android:protectionLevel="signature" />
     <uses-permission android:name="android.permission.BIND_NETWORK_RECOMMENDATION_SERVICE"/>
 
+    <!-- Allows an application to enable, disable and change priority of
+         runtime resource overlays.
+         @hide -->
+    <permission android:name="android.permission.CHANGE_OVERLAY_PACKAGES"
+        android:protectionLevel="signature|privileged|development" />
+
     <!-- ========================================= -->
     <!-- Permissions for special development tools -->
     <!-- ========================================= -->
@@ -2484,7 +2504,7 @@
     <!-- Allows an application to request installing packages. Apps
          targeting APIs greater than 25 must hold this permission in
          order to use {@link android.content.Intent#ACTION_INSTALL_PACKAGE}.
-         <p>Protection level: normal
+         <p>Protection level: signature
     -->
     <permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"
         android:label="@string/permlab_requestInstallPackages"
diff --git a/libs/androidfw/tests/data/lib/AndroidManifest.xml b/core/res/res/color/text_color_secondary.xml
similarity index 61%
copy from libs/androidfw/tests/data/lib/AndroidManifest.xml
copy to core/res/res/color/text_color_secondary.xml
index 02f5d3e..60e0af8 100644
--- a/libs/androidfw/tests/data/lib/AndroidManifest.xml
+++ b/core/res/res/color/text_color_secondary.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 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,7 +14,10 @@
      limitations under the License.
 -->
 
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.lib">
-    <application />
-</manifest>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false"
+        android:alpha="?attr/disabledAlpha"
+        android:color="?attr/colorForeground"/>
+    <item android:alpha="?attr/secondaryContentAlpha"
+        android:color="?attr/colorForeground"/>
+</selector>
diff --git a/core/res/res/drawable/ic_signal_wifi_badged_0_bars.xml b/core/res/res/drawable/ic_signal_wifi_badged_0_bars.xml
index bd1eb41..606b686 100644
--- a/core/res/res/drawable/ic_signal_wifi_badged_0_bars.xml
+++ b/core/res/res/drawable/ic_signal_wifi_badged_0_bars.xml
@@ -13,11 +13,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<vector xmlns:api24="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:viewportWidth="18"
     android:viewportHeight="18"
-    android:width="18dp"
-    android:height="18dp">
+    android:width="26dp"
+    android:height="24dp">
     <group
         android:translateX="386"
         android:translateY="-298">
diff --git a/core/res/res/drawable/ic_signal_wifi_badged_1_bar.xml b/core/res/res/drawable/ic_signal_wifi_badged_1_bar.xml
index aedb12c..a4c5bc2 100644
--- a/core/res/res/drawable/ic_signal_wifi_badged_1_bar.xml
+++ b/core/res/res/drawable/ic_signal_wifi_badged_1_bar.xml
@@ -13,11 +13,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<vector xmlns:api24="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:viewportWidth="18"
     android:viewportHeight="18"
-    android:width="18dp"
-    android:height="18dp">
+    android:width="26dp"
+    android:height="24dp">
     <group
         android:translateX="386"
         android:translateY="-298">
diff --git a/core/res/res/drawable/ic_signal_wifi_badged_2_bars.xml b/core/res/res/drawable/ic_signal_wifi_badged_2_bars.xml
index 6f07cb5..9c27833 100644
--- a/core/res/res/drawable/ic_signal_wifi_badged_2_bars.xml
+++ b/core/res/res/drawable/ic_signal_wifi_badged_2_bars.xml
@@ -13,11 +13,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<vector xmlns:api24="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:viewportWidth="18"
     android:viewportHeight="18"
-    android:width="18dp"
-    android:height="18dp">
+    android:width="26dp"
+    android:height="24dp">
     <group
         android:translateX="386"
         android:translateY="-298">
diff --git a/core/res/res/drawable/ic_signal_wifi_badged_3_bars.xml b/core/res/res/drawable/ic_signal_wifi_badged_3_bars.xml
index c41a8ca..6d693f1 100644
--- a/core/res/res/drawable/ic_signal_wifi_badged_3_bars.xml
+++ b/core/res/res/drawable/ic_signal_wifi_badged_3_bars.xml
@@ -13,11 +13,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<vector xmlns:api24="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:viewportWidth="18"
     android:viewportHeight="18"
-    android:width="18dp"
-    android:height="18dp">
+    android:width="26dp"
+    android:height="24dp">
     <group
         android:translateX="386"
         android:translateY="-298">
diff --git a/core/res/res/drawable/ic_signal_wifi_badged_4_bars.xml b/core/res/res/drawable/ic_signal_wifi_badged_4_bars.xml
index ec0a52f..c48fa36 100644
--- a/core/res/res/drawable/ic_signal_wifi_badged_4_bars.xml
+++ b/core/res/res/drawable/ic_signal_wifi_badged_4_bars.xml
@@ -13,11 +13,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<vector xmlns:api24="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:viewportWidth="18"
     android:viewportHeight="18"
-    android:width="18dp"
-    android:height="18dp">
+    android:width="26dp"
+    android:height="24dp">
     <group
         android:translateX="386"
         android:translateY="-298">
diff --git a/core/res/res/drawable/ic_signal_wifi_badged_4k.xml b/core/res/res/drawable/ic_signal_wifi_badged_4k.xml
index 78bd0a0..0868845 100644
--- a/core/res/res/drawable/ic_signal_wifi_badged_4k.xml
+++ b/core/res/res/drawable/ic_signal_wifi_badged_4k.xml
@@ -13,11 +13,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<vector xmlns:api24="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:viewportWidth="18"
     android:viewportHeight="18"
-    android:width="18dp"
-    android:height="18dp">
+    android:width="26dp"
+    android:height="24dp">
     <group
         android:translateX="386"
         android:translateY="-298">
diff --git a/core/res/res/drawable/ic_signal_wifi_badged_hd.xml b/core/res/res/drawable/ic_signal_wifi_badged_hd.xml
index 78085c2f..657f5ed 100644
--- a/core/res/res/drawable/ic_signal_wifi_badged_hd.xml
+++ b/core/res/res/drawable/ic_signal_wifi_badged_hd.xml
@@ -13,11 +13,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<vector xmlns:api24="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:viewportWidth="18"
     android:viewportHeight="18"
-    android:width="18dp"
-    android:height="18dp">
+    android:width="26dp"
+    android:height="24dp">
     <group
         android:translateX="386"
         android:translateY="-298">
diff --git a/core/res/res/drawable/ic_signal_wifi_badged_ld.xml b/core/res/res/drawable/ic_signal_wifi_badged_ld.xml
index f660ab7..e2971aa 100644
--- a/core/res/res/drawable/ic_signal_wifi_badged_ld.xml
+++ b/core/res/res/drawable/ic_signal_wifi_badged_ld.xml
@@ -13,11 +13,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<vector xmlns:api24="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:viewportWidth="18"
     android:viewportHeight="18"
-    android:width="18dp"
-    android:height="18dp">
+    android:width="26dp"
+    android:height="24dp">
     <group
         android:translateX="386"
         android:translateY="-298">
diff --git a/core/res/res/drawable/ic_signal_wifi_badged_sd.xml b/core/res/res/drawable/ic_signal_wifi_badged_sd.xml
index 43b8653..b073be3 100644
--- a/core/res/res/drawable/ic_signal_wifi_badged_sd.xml
+++ b/core/res/res/drawable/ic_signal_wifi_badged_sd.xml
@@ -13,11 +13,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<vector xmlns:api24="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:viewportWidth="18"
     android:viewportHeight="18"
-    android:width="18dp"
-    android:height="18dp">
+    android:width="26dp"
+    android:height="24dp">
     <group
         android:translateX="386"
         android:translateY="-298">
diff --git a/core/res/res/drawable/ic_wifi_signal_0.xml b/core/res/res/drawable/ic_wifi_signal_0.xml
new file mode 100644
index 0000000..e732a8d
--- /dev/null
+++ b/core/res/res/drawable/ic_wifi_signal_0.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+  android:width="26dp"
+  android:height="24dp"
+  android:viewportWidth="26"
+  android:viewportHeight="24">
+  <path
+    android:fillAlpha="0.3"
+    android:fillColor="#FFFFFF"
+    android:pathData="M13.0,22.0L25.6,6.5C25.1,6.1 20.3,2.1 13.0,2.1S0.9,6.1 0.4,6.5L13.0,22.0L13.0,22.0L13.0,22.0L13.0,22.0L13.0,22.0z"/>
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_wifi_signal_1.xml b/core/res/res/drawable/ic_wifi_signal_1.xml
new file mode 100644
index 0000000..3d006953
--- /dev/null
+++ b/core/res/res/drawable/ic_wifi_signal_1.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="26dp"
+    android:height="24dp"
+    android:viewportWidth="26"
+    android:viewportHeight="24">
+    <path
+        android:fillAlpha="0.3"
+        android:fillColor="#FFFFFF"
+        android:pathData="M13.1,22.0L25.6,6.5C25.1,6.1 20.3,2.1 13.0,2.1S0.9,6.1 0.5,6.5L13.1,22.0L13.1,22.0L13.1,22.0L13.1,22.0L13.1,22.0z"/>
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M13.1,22.0l5.5,-6.8c-0.2,-0.2 -2.3,-1.9 -5.5,-1.9s-5.3,1.8 -5.5,1.9L13.1,22.0L13.1,22.0L13.1,22.0L13.1,22.0L13.1,22.0z"/>
+</vector>
diff --git a/core/res/res/drawable/ic_wifi_signal_2.xml b/core/res/res/drawable/ic_wifi_signal_2.xml
new file mode 100644
index 0000000..2cce9e9
--- /dev/null
+++ b/core/res/res/drawable/ic_wifi_signal_2.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="26dp"
+    android:height="24dp"
+    android:viewportWidth="26"
+    android:viewportHeight="24">
+    <path
+        android:fillAlpha="0.3"
+        android:fillColor="#FFFFFF"
+        android:pathData="M13.0,22.0L25.6,6.5C25.1,6.1 20.3,2.1 13.0,2.1S0.9,6.1 0.4,6.5L13.0,22.0L13.0,22.0L13.0,22.0L13.0,22.0L13.0,22.0z"/>
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M13.0,22.0l7.6,-9.4C20.3,12.4 17.4,10.0 13.0,10.0s-7.3,2.4 -7.6,2.7L13.0,22.0L13.0,22.0L13.0,22.0L13.0,22.0L13.0,22.0z"/>
+</vector>
diff --git a/core/res/res/drawable/ic_wifi_signal_3.xml b/core/res/res/drawable/ic_wifi_signal_3.xml
new file mode 100644
index 0000000..d3b3d3a
--- /dev/null
+++ b/core/res/res/drawable/ic_wifi_signal_3.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="26dp"
+    android:height="24dp"
+    android:viewportWidth="26"
+    android:viewportHeight="24">
+    <path
+        android:fillAlpha="0.3"
+        android:fillColor="#FFFFFF"
+        android:pathData="M13.0,22.0L25.6,6.5C25.1,6.1 20.3,2.1 13.0,2.1S0.9,6.1 0.4,6.5L13.0,22.0L13.0,22.0L13.0,22.0L13.0,22.0L13.0,22.0z"/>
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M13.0,22.0l9.2,-11.4c-0.4,-0.3 -3.9,-3.2 -9.2,-3.2s-8.9,3.0 -9.2,3.2L13.0,22.0L13.0,22.0L13.0,22.0L13.0,22.0L13.0,22.0z"/>
+</vector>
diff --git a/core/res/res/drawable/ic_wifi_signal_4.xml b/core/res/res/drawable/ic_wifi_signal_4.xml
new file mode 100644
index 0000000..aca4551
--- /dev/null
+++ b/core/res/res/drawable/ic_wifi_signal_4.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2015 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="26dp"
+    android:height="24dp"
+    android:viewportWidth="26"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M13.0,22.0L25.6,6.5C25.1,6.1 20.3,2.1 13.0,2.1S0.9,6.1 0.4,6.5L13.0,22.0L13.0,22.0L13.0,22.0L13.0,22.0L13.0,22.0z"/>
+</vector>
diff --git a/core/res/res/layout/autofill_save.xml b/core/res/res/layout/autofill_save.xml
new file mode 100644
index 0000000..d55a012
--- /dev/null
+++ b/core/res/res/layout/autofill_save.xml
@@ -0,0 +1,57 @@
+<?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.
+-->
+
+<!-- TODO(b/33197203) remove hardcoded color once color is final -->
+<RelativeLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
+    android:paddingTop="16dip"
+    android:paddingBottom="16dip"
+    android:background="#FDF8C8">
+
+  <!-- TODO(b/33197203) use.R.string once final wording is done -->
+  <TextView
+      android:id="@+id/autofill_save_title"
+      android:layout_width="match_parent"
+      android:layout_height="wrap_content"
+      android:text="Save for autofill?"
+      android:singleLine="true"/>
+
+  <TextView
+      android:id="@+id/autofill_save_no"
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+      android:layout_below="@+id/autofill_save_title"
+      android:layout_toLeftOf="@+id/autofill_save_yes"
+      android:layout_marginRight="16dip"
+      android:text="No thanks"
+      android:textAllCaps="true"
+      android:singleLine="true"/>
+
+    <TextView
+      android:id="@+id/autofill_save_yes"
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+      android:layout_below="@+id/autofill_save_title"
+      android:layout_alignParentRight="true"
+      android:text="Save"
+      android:textAllCaps="true"
+      android:singleLine="true"/>
+
+</RelativeLayout>
diff --git a/core/res/res/layout/notification_template_material_ambient.xml b/core/res/res/layout/notification_template_material_ambient.xml
index 1ae317c..e2c68b5 100644
--- a/core/res/res/layout/notification_template_material_ambient.xml
+++ b/core/res/res/layout/notification_template_material_ambient.xml
@@ -52,19 +52,18 @@
                 android:ellipsize="marquee"
                 android:fadingEdge="horizontal"
                 android:textSize="20sp"
-                android:textColor="@android:color/white"
+                android:textColor="#e6fafafa"
             />
             <TextView android:id="@+id/text"
                 android:layout_width="match_parent"
                 android:layout_height="0dp"
-                android:paddingBottom="@dimen/notification_content_margin_bottom"
                 android:textAppearance="@style/TextAppearance.Material.Notification"
                 android:singleLine="false"
                 android:layout_weight="1"
                 android:gravity="top"
                 android:visibility="gone"
-                android:textSize="18sp"
-                android:textColor="@android:color/white"
+                android:textSize="16sp"
+                android:textColor="#ccfafafa"
                 android:layout_marginTop="4dp"
             />
         </LinearLayout>
diff --git a/core/res/res/layout/search_view.xml b/core/res/res/layout/search_view.xml
index 72588c7..0c462fd 100644
--- a/core/res/res/layout/search_view.xml
+++ b/core/res/res/layout/search_view.xml
@@ -43,7 +43,8 @@
         android:layout_height="match_parent"
         android:layout_gravity="center_vertical"
         android:focusable="true"
-        android:contentDescription="@string/searchview_description_search" />
+        android:contentDescription="@string/searchview_description_search"
+        android:tooltipText="@string/searchview_description_search" />
 
     <LinearLayout
         android:id="@+id/search_edit_frame"
diff --git a/core/res/res/values-mcc208-mnc10/config.xml b/core/res/res/values-mcc208-mnc10/config.xml
index d3640e5..3ed7818 100644
--- a/core/res/res/values-mcc208-mnc10/config.xml
+++ b/core/res/res/values-mcc208-mnc10/config.xml
@@ -31,28 +31,4 @@
         <item>[ApnSettingV3]INTERNET NRJ,internetnrj,,,,,,,,,208,10,,DUN,,,true,0,,,,,,,gid,4E</item>
     </string-array>
 
-    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
-        <item>21401</item>
-        <item>21402</item>
-        <item>21403</item>
-        <item>21404</item>
-        <item>21405</item>
-        <item>21406</item>
-        <item>21407</item>
-        <item>21408</item>
-        <item>21409</item>
-        <item>21410</item>
-        <item>21411</item>
-        <item>21412</item>
-        <item>21413</item>
-        <item>21414</item>
-        <item>21415</item>
-        <item>21416</item>
-        <item>21417</item>
-        <item>21418</item>
-        <item>21419</item>
-        <item>21420</item>
-        <item>21421</item>
-    </string-array>
-
 </resources>
diff --git a/core/res/res/values-mcc334-mnc050/config.xml b/core/res/res/values-mcc334-mnc050/config.xml
index f6777d0..616a8e8 100644
--- a/core/res/res/values-mcc334-mnc050/config.xml
+++ b/core/res/res/values-mcc334-mnc050/config.xml
@@ -40,4 +40,8 @@
       <item>Modem,modem.iusacellgsm.mx,,,iusacellgsm,iusacellgsm,,,,,334,050,1,DUN</item>
     </string-array>
 
+    <!-- Do not translate. Defines the slots is Two Digit Number for dialing normally not USSD -->
+    <string-array translatable="false" name="config_twoDigitNumberPattern">
+        <item>"#9"</item>
+    </string-array>
 </resources>
diff --git a/core/res/res/values-mcc334-mnc090/config.xml b/core/res/res/values-mcc334-mnc090/config.xml
new file mode 100644
index 0000000..1632a42
--- /dev/null
+++ b/core/res/res/values-mcc334-mnc090/config.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Do not translate. Defines the slots is Two Digit Number for dialing normally not USSD -->
+
+    <string-array translatable="false" name="config_twoDigitNumberPattern">
+        <item>"#9"</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index c333629..34f78f3 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -64,6 +64,8 @@
         <attr name="disabledAlpha" format="float" />
         <!-- The alpha applied to the foreground color to create the primary text color. -->
         <attr name="primaryContentAlpha" format="float" />
+        <!-- The alpha applied to the foreground color to create the secondary text color. -->
+        <attr name="secondaryContentAlpha" format="float" />
         <!-- Default background dim amount when a menu, dialog, or something similar pops up. -->
         <attr name="backgroundDimAmount" format="float" />
         <!-- Control whether dimming behind the window is enabled.  The default
@@ -2500,13 +2502,13 @@
         <!-- Sets the id of a view before which this one is visited in accessibility traversal.
              A screen-reader must visit the content of this view before the content of the one
              it precedes.
-             @see android.view.View#setAccessibilityTraversalBefore(int)} -->
+             {@see android.view.View#setAccessibilityTraversalBefore(int)} -->
         <attr name="accessibilityTraversalBefore" format="integer" />
 
         <!-- Sets the id of a view after which this one is visited in accessibility traversal.
              A screen-reader must visit the content of the other view before the content of
              this one.
-             @see android.view.View#setAccessibilityTraversalAfter(int)} -->
+             {@see android.view.View#setAccessibilityTraversalAfter(int)} -->
         <attr name="accessibilityTraversalAfter" format="integer" />
 
         <!-- Name of the method in this View's context to invoke when the view is
@@ -3266,8 +3268,8 @@
         <!-- The unique id for the subtype. The text service (spell checker) framework keeps track
              of enabled subtypes by ID. When the spell checker package gets upgraded, enabled IDs
              will stay enabled even if other attributes are different. If the ID is unspecified or
-             or explicitly specified to 0 in XML resources,
-             {@code Arrays.hashCode(new Object[] {subtypeLocale, extraValue}) will be used instead.
+             explicitly specified to 0 in XML resources,
+             {@code Arrays.hashCode(new Object[] {subtypeLocale, extraValue})} will be used instead.
               -->
         <attr name="subtypeId" />
         <!-- The BCP-47 Language Tag of the subtype.  This replaces
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 0dde91b..82e33f8 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -2373,7 +2373,7 @@
     </declare-styleable>
 
     <!-- Declaration of an {@link android.content.Intent} object in XML.  May
-         also include zero or more {@link #IntentCategory <category> and
+         also include zero or more {@link #IntentCategory <category>} and
          {@link #Extra <extra>} tags. -->
     <declare-styleable name="Intent">
         <!-- The action name to assign to the Intent, as per
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 4164e5d..b28c6f2 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -89,7 +89,7 @@
     <color name="perms_dangerous_perm_color">#33b5e5</color>
     <color name="shadow">#cc222222</color>
     <color name="perms_costs_money">#fff4511e</color>
-    
+
     <!-- For search-related UIs -->
     <color name="search_url_text_normal">#7fa87f</color>
     <color name="search_url_text_selected">@android:color/black</color>
@@ -132,6 +132,10 @@
     <drawable name="notification_template_icon_low_bg">#0cffffff</drawable>
     <drawable name="notification_template_divider">#29000000</drawable>
     <drawable name="notification_template_divider_media">#29ffffff</drawable>
+    <color name="notification_primary_text_color_light">@color/primary_text_default_material_light</color>
+    <color name="notification_primary_text_color_dark">@color/primary_text_default_material_dark</color>
+    <color name="notification_secondary_text_color_light">@color/secondary_text_material_light</color>
+    <color name="notification_secondary_text_color_dark">@color/secondary_text_material_dark</color>
 
     <color name="notification_material_background_color">#ffffffff</color>
 
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index db89c22..0a24565 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -78,6 +78,8 @@
     <item name="disabled_alpha_material_dark" format="float" type="dimen">0.30</item>
     <item name="primary_content_alpha_material_light" format="float" type="dimen">1</item>
     <item name="primary_content_alpha_material_dark" format="float" type="dimen">0.87</item>
+    <item name="secondary_content_alpha_material_light" format="float" type="dimen">.7</item>
+    <item name="secondary_content_alpha_material_dark" format="float" type="dimen">0.54</item>
 
     <item name="highlight_alpha_material_light" format="float" type="dimen">0.12</item>
     <item name="highlight_alpha_material_dark" format="float" type="dimen">0.20</item>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 6a8b556..9873762 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2278,6 +2278,13 @@
     <!-- Whether to use voip audio mode for ims call -->
     <bool name="config_use_voip_mode_for_ims">false</bool>
 
+    <!-- ImsService package name to bind to by default. If none is specified in an overlay, an
+         empty string is passed in -->
+    <string name="config_ims_package"/>
+
+    <!-- Flag specifying whether or not IMS will use the dynamic ImsResolver -->
+    <bool name="config_dynamic_bind_ims">true</bool>
+
     <bool name="config_networkSamplingWakesDevice">true</bool>
 
     <string-array translatable="false" name="config_cdma_home_system" />
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index e6358a3..4266f88 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -488,6 +488,9 @@
     <!-- The default minimal size of a resizable task, in both dimensions. -->
     <dimen name="default_minimal_size_resizable_task">220dp</dimen>
 
+    <!-- Height of a task when in minimized mode from the top when launcher is resizable. -->
+    <dimen name="task_height_of_minimized_mode">80dp</dimen>
+
     <!-- Minimum "smallest width" of the display for cascading menus to be enabled. -->
     <dimen name="cascading_menus_min_smallest_width">720dp</dimen>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 1146871..f981029 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2800,6 +2800,7 @@
     </public-group>
 
     <public type="attr" name="primaryContentAlpha" />
+    <public type="attr" name="secondaryContentAlpha" />
 
   <!-- ===============================================================
        DO NOT ADD UN-GROUPED ITEMS HERE
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 0b326e9..1e15348 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -451,14 +451,14 @@
     </style>
 
     <style name="TextAppearance.Material.Notification">
-        <item name="textColor">@color/secondary_text_material_light</item>
+        <item name="textColor">@color/notification_secondary_text_color_light</item>
         <item name="textSize">@dimen/notification_text_size</item>
     </style>
 
     <style name="TextAppearance.Material.Notification.Reply" />
 
     <style name="TextAppearance.Material.Notification.Title">
-        <item name="textColor">@color/primary_text_default_material_light</item>
+        <item name="textColor">@color/notification_primary_text_color_light</item>
         <item name="textSize">@dimen/notification_title_text_size</item>
     </style>
 
@@ -467,7 +467,7 @@
     </style>
 
     <style name="TextAppearance.Material.Notification.Info">
-        <item name="textColor">@color/secondary_text_default_material_light</item>
+        <item name="textColor">@color/notification_secondary_text_color_light</item>
         <item name="textSize">@dimen/notification_subtext_size</item>
     </style>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 78f6b49..554e123 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -254,6 +254,8 @@
   <java-symbol type="bool" name="config_enableBurnInProtection" />
   <java-symbol type="bool" name="config_hotswapCapable" />
   <java-symbol type="bool" name="config_mms_content_disposition_support" />
+  <java-symbol type="string" name="config_ims_package" />
+  <java-symbol type="bool" name="config_dynamic_bind_ims" />
   <java-symbol type="bool" name="config_networkSamplingWakesDevice" />
   <java-symbol type="bool" name="config_showMenuShortcutsWhenKeyboardPresent" />
   <java-symbol type="bool" name="config_sip_wifi_only" />
@@ -504,7 +506,6 @@
   <java-symbol type="string" name="NetworkPreferenceSwitchTitle" />
   <java-symbol type="string" name="SetupCallDefault" />
   <java-symbol type="string" name="accept" />
-  <java-symbol type="string" name="accessibility_enabled" />
   <java-symbol type="string" name="activity_chooser_view_see_all" />
   <java-symbol type="string" name="activitychooserview_choose_application" />
   <java-symbol type="string" name="activitychooserview_choose_application_error" />
@@ -601,7 +602,6 @@
   <java-symbol type="string" name="contentServiceSync" />
   <java-symbol type="string" name="contentServiceSyncNotificationTitle" />
   <java-symbol type="string" name="contentServiceTooManyDeletesNotificationDesc" />
-  <java-symbol type="string" name="continue_to_enable_accessibility" />
   <java-symbol type="string" name="date_and_time" />
   <java-symbol type="string" name="date_picker_decrement_day_button" />
   <java-symbol type="string" name="date_picker_decrement_month_button" />
@@ -648,7 +648,6 @@
   <java-symbol type="string" name="widget_default_class_name" />
   <java-symbol type="string" name="emergency_calls_only" />
   <java-symbol type="array" name="config_ephemeralResolverPackage" />
-  <java-symbol type="string" name="enable_accessibility_canceled" />
   <java-symbol type="string" name="eventTypeAnniversary" />
   <java-symbol type="string" name="eventTypeBirthday" />
   <java-symbol type="string" name="eventTypeCustom" />
@@ -1256,6 +1255,11 @@
   <java-symbol type="drawable" name="platlogo" />
   <java-symbol type="drawable" name="stat_notify_sync_error" />
   <java-symbol type="drawable" name="stat_notify_wifi_in_range" />
+  <java-symbol type="drawable" name="ic_wifi_signal_0" />
+  <java-symbol type="drawable" name="ic_wifi_signal_1" />
+  <java-symbol type="drawable" name="ic_wifi_signal_2" />
+  <java-symbol type="drawable" name="ic_wifi_signal_3" />
+  <java-symbol type="drawable" name="ic_wifi_signal_4" />
   <java-symbol type="drawable" name="ic_signal_wifi_badged_0_bars" />
   <java-symbol type="drawable" name="ic_signal_wifi_badged_1_bar" />
   <java-symbol type="drawable" name="ic_signal_wifi_badged_2_bars" />
@@ -1772,6 +1776,7 @@
   <java-symbol type="id" name="replace_message" />
   <java-symbol type="fraction" name="config_dimBehindFadeDuration" />
   <java-symbol type="dimen" name="default_minimal_size_resizable_task" />
+  <java-symbol type="dimen" name="task_height_of_minimized_mode" />
   <java-symbol type="fraction" name="config_screenAutoBrightnessDozeScaleFactor" />
   <java-symbol type="fraction" name="config_autoBrightnessAdjustmentMaxGamma" />
   <java-symbol type="integer" name="config_autoBrightnessAmbientLightHorizon"/>
@@ -2791,6 +2796,11 @@
   <java-symbol type="string" name="notification_header_divider_symbol_with_spaces" />
   <java-symbol type="string" name="config_defaultCellBroadcastReceiverComponent" />
 
+  <java-symbol type="color" name="notification_primary_text_color_light" />
+  <java-symbol type="color" name="notification_primary_text_color_dark" />
+  <java-symbol type="color" name="notification_secondary_text_color_light" />
+  <java-symbol type="color" name="notification_secondary_text_color_dark" />
+
   <java-symbol type="string" name="app_category_game" />
   <java-symbol type="string" name="app_category_audio" />
   <java-symbol type="string" name="app_category_video" />
@@ -2804,8 +2814,6 @@
 
   <java-symbol type="string" name="config_icon_mask" />
 
-  <java-symbol type="attr" name="primaryContentAlpha" />
-
   <!-- Accessibility Shortcut -->
   <java-symbol type="string" name="accessibility_shortcut_warning_dialog_title" />
   <java-symbol type="string" name="accessibility_shortcut_toogle_warning" />
@@ -2820,4 +2828,10 @@
   <java-symbol type="dimen" name="item_touch_helper_max_drag_scroll_per_frame"/>
   <java-symbol type="dimen" name="item_touch_helper_swipe_escape_velocity"/>
   <java-symbol type="dimen" name="item_touch_helper_swipe_escape_max_velocity"/>
+
+  <!-- com.android.server.autofill -->
+  <java-symbol type="layout" name="autofill_save"/>
+  <java-symbol type="id" name="autofill_save_title" />
+  <java-symbol type="id" name="autofill_save_no" />
+  <java-symbol type="id" name="autofill_save_yes" />
 </resources>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 3587fec..b063baf 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -49,6 +49,7 @@
         <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_material_dark</item>
         <item name="disabledAlpha">@dimen/disabled_alpha_material_dark</item>
         <item name="primaryContentAlpha">@dimen/primary_content_alpha_material_dark</item>
+        <item name="secondaryContentAlpha">@dimen/secondary_content_alpha_material_dark</item>
         <item name="backgroundDimAmount">0.6</item>
 
         <!-- Text styles -->
@@ -59,7 +60,7 @@
         <item name="textColorPrimaryInverse">@color/primary_text_material_light</item>
         <item name="textColorPrimaryActivated">@color/primary_text_inverse_when_activated_material</item>
         <item name="textColorPrimaryDisableOnly">@color/primary_text_disable_only_material_dark</item>
-        <item name="textColorSecondary">@color/secondary_text_material_dark</item>
+        <item name="textColorSecondary">@color/text_color_secondary</item>
         <item name="textColorSecondaryInverse">@color/secondary_text_material_light</item>
         <item name="textColorSecondaryActivated">@color/secondary_text_inverse_when_activated_material</item>
         <item name="textColorTertiary">@color/secondary_text_material_dark</item>
@@ -415,6 +416,7 @@
         <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_material_light</item>
         <item name="disabledAlpha">@dimen/disabled_alpha_material_light</item>
         <item name="primaryContentAlpha">@dimen/primary_content_alpha_material_light</item>
+        <item name="secondaryContentAlpha">@dimen/secondary_content_alpha_material_light</item>
         <item name="backgroundDimAmount">0.6</item>
 
         <!-- Text styles -->
@@ -424,7 +426,7 @@
         <item name="textColorPrimary">@color/text_color_primary</item>
         <item name="textColorPrimaryInverse">@color/primary_text_material_dark</item>
         <item name="textColorPrimaryActivated">@color/primary_text_inverse_when_activated_material</item>
-        <item name="textColorSecondary">@color/secondary_text_material_light</item>
+        <item name="textColorSecondary">@color/text_color_secondary</item>
         <item name="textColorSecondaryInverse">@color/secondary_text_material_dark</item>
         <item name="textColorSecondaryActivated">@color/secondary_text_inverse_when_activated_material</item>
         <item name="textColorTertiary">@color/secondary_text_material_light</item>
@@ -809,7 +811,7 @@
 
         <item name="textColorPrimary">@color/text_color_primary</item>
         <item name="textColorPrimaryInverse">@color/primary_text_material_dark</item>
-        <item name="textColorSecondary">@color/secondary_text_material_light</item>
+        <item name="textColorSecondary">@color/text_color_secondary</item>
         <item name="textColorSecondaryInverse">@color/secondary_text_material_dark</item>
         <item name="textColorTertiary">@color/secondary_text_material_light</item>
         <item name="textColorTertiaryInverse">@color/secondary_text_material_dark</item>
@@ -844,7 +846,7 @@
         <item name="textColorPrimary">@color/text_color_primary</item>
         <item name="textColorPrimaryInverse">@color/primary_text_material_light</item>
         <item name="textColorPrimaryDisableOnly">@color/primary_text_disable_only_material_dark</item>
-        <item name="textColorSecondary">@color/secondary_text_material_dark</item>
+        <item name="textColorSecondary">@color/text_color_secondary</item>
         <item name="textColorSecondaryInverse">@color/secondary_text_material_light</item>
         <item name="textColorTertiary">@color/secondary_text_material_dark</item>
         <item name="textColorTertiaryInverse">@color/secondary_text_material_light</item>
diff --git a/core/tests/coretests/src/android/metrics/LogMakerTest.java b/core/tests/coretests/src/android/metrics/LogMakerTest.java
index 35d8d93..b9c973f 100644
--- a/core/tests/coretests/src/android/metrics/LogMakerTest.java
+++ b/core/tests/coretests/src/android/metrics/LogMakerTest.java
@@ -115,6 +115,13 @@
         assertEquals(10, out[1]);
     }
 
+    public void testClearData() {
+        LogMaker builder = new LogMaker(0);
+        builder.addTaggedData(1, "onetwothree");
+        builder.clearTaggedData(1);
+        assertEquals(null, builder.getTaggedData(1));
+    }
+
     public void testGiantLogOmitted() {
         LogMaker badBuilder = new LogMaker(0);
         StringBuilder b = new StringBuilder();
@@ -125,4 +132,78 @@
         assertTrue(badBuilder.serialize().length < LogMaker.MAX_SERIALIZED_SIZE);
     }
 
+    public void testIdentityEquality() {
+        LogMaker a = new LogMaker(0);
+        a.addTaggedData(1, "onetwothree");
+        a.addTaggedData(2, 123);
+        a.addTaggedData(3, 123L);
+
+        assertTrue("objects should be equal to themselves", a.isSubsetOf(a));
+    }
+
+    public void testExactEquality() {
+        LogMaker a = new LogMaker(0);
+        a.addTaggedData(1, "onetwothree");
+        a.addTaggedData(2, 123);
+        a.addTaggedData(3, 123L);
+        LogMaker b = new LogMaker(0);
+        b.addTaggedData(1, "onetwothree");
+        b.addTaggedData(2, 123);
+        b.addTaggedData(3, 123L);
+
+        assertTrue("deep equality should be true", a.isSubsetOf(b));
+        assertTrue("deep equality shoudl be true", b.isSubsetOf(a));
+    }
+
+    public void testSubsetEquality() {
+        LogMaker a = new LogMaker(0);
+        a.addTaggedData(1, "onetwothree");
+        a.addTaggedData(2, 123);
+        LogMaker b = new LogMaker(0);
+        b.addTaggedData(1, "onetwothree");
+        b.addTaggedData(2, 123);
+        b.addTaggedData(3, 123L);
+
+        assertTrue("a is a strict subset of b", a.isSubsetOf(b));
+        assertTrue("b is not a strict subset of a", !b.isSubsetOf(a));
+    }
+
+    public void testInequality() {
+        LogMaker a = new LogMaker(0);
+        a.addTaggedData(1, "onetwofour");
+        a.addTaggedData(2, 1234);
+        LogMaker b = new LogMaker(0);
+        b.addTaggedData(1, "onetwothree");
+        b.addTaggedData(2, 123);
+        b.addTaggedData(3, 123L);
+
+        assertTrue("a is not a subset of b", !a.isSubsetOf(b));
+        assertTrue("b is not a subset of a", !b.isSubsetOf(a));
+    }
+
+    public void testWildcardEquality() {
+        LogMaker empty = new LogMaker(0);
+        empty.clearTaggedData(MetricsEvent.RESERVED_FOR_LOGBUILDER_CATEGORY);  //dirty trick
+        LogMaker b = new LogMaker(0);
+        b.addTaggedData(1, "onetwothree");
+        b.addTaggedData(2, 123);
+        b.addTaggedData(3, 123L);
+
+        assertTrue("empty builder is a subset of anything", empty.isSubsetOf(b));
+    }
+
+    public void testNullEquality() {
+        LogMaker a = new LogMaker(0);
+        a.addTaggedData(1, "onetwofour");
+        a.addTaggedData(2, 1234);
+
+        assertTrue("a is not a subset of null", !a.isSubsetOf(null));
+    }
+
+    public void testMajorCategory() {
+        LogMaker a = new LogMaker(1);
+        LogMaker b = new LogMaker(2);
+        assertFalse(a.isSubsetOf(b));
+        assertFalse(b.isSubsetOf(a));
+    }
 }
diff --git a/core/tests/coretests/src/android/provider/SettingsTest.java b/core/tests/coretests/src/android/provider/SettingsTest.java
new file mode 100644
index 0000000..0c9c3c17
--- /dev/null
+++ b/core/tests/coretests/src/android/provider/SettingsTest.java
@@ -0,0 +1,541 @@
+/*
+ * 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.provider;
+
+import static com.google.android.collect.Sets.newHashSet;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.is;
+import static java.lang.reflect.Modifier.isFinal;
+import static java.lang.reflect.Modifier.isPublic;
+import static java.lang.reflect.Modifier.isStatic;
+
+import android.annotation.TargetApi;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import java.lang.reflect.Field;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** Unit test for Settings. */
+@TargetApi(26)
+@RunWith(AndroidJUnit4.class)
+public class SettingsTest {
+
+    /**
+     * The following blacklists contain settings that should *not* be backed up and restored to
+     * another device.  As a general rule, anything that is not user configurable should be
+     * blacklisted (and conversely, things that *are* user configurable *should* be backed up)
+     */
+    private static final Set<String> BACKUP_BLACKLISTED_SYSTEM_SETTINGS =
+            newHashSet(
+                    Settings.System.ADVANCED_SETTINGS, // candidate for backup?
+                    Settings.System.ALARM_ALERT, // backup candidate?
+                    Settings.System.ALARM_ALERT_CACHE, // internal cache
+                    Settings.System.APPEND_FOR_LAST_AUDIBLE, // suffix deprecated since API 2
+                    Settings.System.EGG_MODE, // I am the lolrus
+                    Settings.System.END_BUTTON_BEHAVIOR, // bug?
+                    Settings.System
+                            .HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, // candidate for backup?
+                    Settings.System.LOCKSCREEN_DISABLED, // ?
+                    Settings.System.MEDIA_BUTTON_RECEIVER, // candidate for backup?
+                    Settings.System.MUTE_STREAMS_AFFECTED, //  candidate for backup?
+                    Settings.System.NOTIFICATION_LIGHT_PULSE, // candidate for backup?
+                    Settings.System.NOTIFICATION_SOUND_CACHE, // internal cache
+                    Settings.System.POINTER_LOCATION, // backup candidate?
+                    Settings.System.RINGTONE_CACHE, // internal cache
+                    Settings.System.SCREEN_BRIGHTNESS_FOR_VR, // bug?
+                    Settings.System.SETUP_WIZARD_HAS_RUN, // Only used by SuW
+                    Settings.System.SHOW_GTALK_SERVICE_STATUS, // candidate for backup?
+                    Settings.System.SHOW_TOUCHES, // bug?
+                    Settings.System.SIP_ADDRESS_ONLY, // value, not a setting
+                    Settings.System.SIP_ALWAYS, // value, not a setting
+                    Settings.System.SYSTEM_LOCALES, // bug?
+                    Settings.System.USER_ROTATION, // backup candidate?
+                    Settings.System.VIBRATE_IN_SILENT, // deprecated?
+                    Settings.System.VIBRATE_ON, // candidate for backup?
+                    Settings.System.VOLUME_ALARM, // deprecated since API 2?
+                    Settings.System.VOLUME_BLUETOOTH_SCO, // deprecated since API 2?
+                    Settings.System.VOLUME_MASTER, // candidate for backup?
+                    Settings.System.VOLUME_MUSIC, // deprecated since API 2?
+                    Settings.System.VOLUME_NOTIFICATION, // deprecated since API 2?
+                    Settings.System.VOLUME_RING, // deprecated since API 2?
+                    Settings.System.VOLUME_SYSTEM, // deprecated since API 2?
+                    Settings.System.VOLUME_VOICE, // deprecated since API 2?
+                    Settings.System.WHEN_TO_MAKE_WIFI_CALLS, // bug?
+                    Settings.System.WINDOW_ORIENTATION_LISTENER_LOG // used for debugging only
+                    );
+
+    private static final Set<String> BACKUP_BLACKLISTED_GLOBAL_SETTINGS =
+            newHashSet(
+                    Settings.Global.ADB_ENABLED,
+                    Settings.Global.ADD_USERS_WHEN_LOCKED,
+                    Settings.Global.AIRPLANE_MODE_ON,
+                    Settings.Global.AIRPLANE_MODE_RADIOS,
+                    Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
+                    Settings.Global.ALARM_MANAGER_CONSTANTS,
+                    Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED,
+                    Settings.Global.ALWAYS_FINISH_ACTIVITIES,
+                    Settings.Global.ANIMATOR_DURATION_SCALE,
+                    Settings.Global.APN_DB_UPDATE_CONTENT_URL,
+                    Settings.Global.APN_DB_UPDATE_METADATA_URL,
+                    Settings.Global.APP_IDLE_CONSTANTS,
+                    Settings.Global.ASSISTED_GPS_ENABLED,
+                    Settings.Global.AUDIO_SAFE_VOLUME_STATE,
+                    Settings.Global.BATTERY_DISCHARGE_DURATION_THRESHOLD,
+                    Settings.Global.BATTERY_DISCHARGE_THRESHOLD,
+                    Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE,
+                    Settings.Global.BLUETOOTH_A2DP_SINK_PRIORITY_PREFIX,
+                    Settings.Global.BLUETOOTH_A2DP_SRC_PRIORITY_PREFIX,
+                    Settings.Global.BLUETOOTH_DISABLED_PROFILES,
+                    Settings.Global.BLUETOOTH_HEADSET_PRIORITY_PREFIX,
+                    Settings.Global.BLUETOOTH_INPUT_DEVICE_PRIORITY_PREFIX,
+                    Settings.Global.BLUETOOTH_INTEROPERABILITY_LIST,
+                    Settings.Global.BLUETOOTH_MAP_CLIENT_PRIORITY_PREFIX,
+                    Settings.Global.BLUETOOTH_MAP_PRIORITY_PREFIX,
+                    Settings.Global.BLUETOOTH_ON, // Candidate for backup?
+                    Settings.Global.BLUETOOTH_PAN_PRIORITY_PREFIX,
+                    Settings.Global.BLUETOOTH_PBAP_CLIENT_PRIORITY_PREFIX,
+                    Settings.Global.BLUETOOTH_SAP_PRIORITY_PREFIX,
+                    Settings.Global.BOOT_COUNT,
+                    Settings.Global.CAPTIVE_PORTAL_FALLBACK_URL,
+                    Settings.Global.CAPTIVE_PORTAL_HTTPS_URL,
+                    Settings.Global.CAPTIVE_PORTAL_HTTP_URL,
+                    Settings.Global.CAPTIVE_PORTAL_MODE,
+                    Settings.Global.CAPTIVE_PORTAL_SERVER,
+                    Settings.Global.CAPTIVE_PORTAL_USE_HTTPS,
+                    Settings.Global.CAPTIVE_PORTAL_USER_AGENT,
+                    Settings.Global.CAR_DOCK_SOUND,
+                    Settings.Global.CARRIER_APP_WHITELIST,
+                    Settings.Global.CAR_UNDOCK_SOUND,
+                    Settings.Global.CDMA_CELL_BROADCAST_SMS,
+                    Settings.Global.CDMA_ROAMING_MODE,
+                    Settings.Global.CDMA_SUBSCRIPTION_MODE,
+                    Settings.Global.CELL_ON,
+                    Settings.Global.CERT_PIN_UPDATE_CONTENT_URL,
+                    Settings.Global.CERT_PIN_UPDATE_METADATA_URL,
+                    Settings.Global.COMPATIBILITY_MODE,
+                    Settings.Global.CONNECTIVITY_CHANGE_DELAY,
+                    Settings.Global.CONNECTIVITY_METRICS_BUFFER_SIZE,
+                    Settings.Global.CONNECTIVITY_SAMPLING_INTERVAL_IN_SECONDS,
+                    Settings.Global.CONTACT_METADATA_SYNC_ENABLED,
+                    Settings.Global.CONTACTS_DATABASE_WAL_ENABLED,
+                    Settings.Global.DATA_ACTIVITY_TIMEOUT_MOBILE,
+                    Settings.Global.DATA_ACTIVITY_TIMEOUT_WIFI,
+                    Settings.Global.DATABASE_DOWNGRADE_REASON,
+                    Settings.Global.DATA_ROAMING,
+                    Settings.Global.DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS,
+                    Settings.Global.DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS,
+                    Settings.Global.DEBUG_APP,
+                    Settings.Global.DEBUG_VIEW_ATTRIBUTES,
+                    Settings.Global.DEFAULT_DNS_SERVER,
+                    Settings.Global.DEFAULT_INSTALL_LOCATION,
+                    Settings.Global.DESK_DOCK_SOUND,
+                    Settings.Global.DESK_UNDOCK_SOUND,
+                    Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT,
+                    Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES,
+                    Settings.Global.DEVELOPMENT_FORCE_RTL,
+                    Settings.Global.DEVELOPMENT_SETTINGS_ENABLED,
+                    Settings.Global.DEVICE_DEMO_MODE,
+                    Settings.Global.DEVICE_IDLE_CONSTANTS,
+                    Settings.Global.DEVICE_IDLE_CONSTANTS_WATCH,
+                    Settings.Global.DEVICE_NAME,
+                    Settings.Global.DEVICE_PROVISIONED,
+                    Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED,
+                    Settings.Global.DISK_FREE_CHANGE_REPORTING_THRESHOLD,
+                    Settings.Global.DISPLAY_SCALING_FORCE,
+                    Settings.Global.DISPLAY_SIZE_FORCED,
+                    Settings.Global.DNS_RESOLVER_MAX_SAMPLES,
+                    Settings.Global.DNS_RESOLVER_MIN_SAMPLES,
+                    Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS,
+                    Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT,
+                    Settings.Global.DOCK_SOUNDS_ENABLED_WHEN_ACCESSIBILITY,
+                    Settings.Global.DOWNLOAD_MAX_BYTES_OVER_MOBILE,
+                    Settings.Global.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE,
+                    Settings.Global.DROPBOX_AGE_SECONDS,
+                    Settings.Global.DROPBOX_MAX_FILES,
+                    Settings.Global.DROPBOX_QUOTA_KB,
+                    Settings.Global.DROPBOX_QUOTA_PERCENT,
+                    Settings.Global.DROPBOX_RESERVE_PERCENT,
+                    Settings.Global.DROPBOX_TAG_PREFIX,
+                    Settings.Global.EMERGENCY_AFFORDANCE_NEEDED,
+                    Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED,
+                    Settings.Global.ENABLE_CELLULAR_ON_BOOT,
+                    Settings.Global.ENABLE_EPHEMERAL_FEATURE,
+                    Settings.Global.ENHANCED_4G_MODE_ENABLED,
+                    Settings.Global.EPHEMERAL_COOKIE_MAX_SIZE_BYTES,
+                    Settings.Global.ERROR_LOGCAT_PREFIX,
+                    Settings.Global.FANCY_IME_ANIMATIONS,
+                    Settings.Global.FORCE_ALLOW_ON_EXTERNAL,
+                    Settings.Global.FSTRIM_MANDATORY_INTERVAL,
+                    Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
+                    Settings.Global.GLOBAL_HTTP_PROXY_HOST,
+                    Settings.Global.GLOBAL_HTTP_PROXY_PAC,
+                    Settings.Global.GLOBAL_HTTP_PROXY_PORT,
+                    Settings.Global.GPRS_REGISTER_CHECK_PERIOD_MS,
+                    Settings.Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED,
+                    Settings.Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED,
+                    Settings.Global.HDMI_CONTROL_ENABLED,
+                    Settings.Global.HDMI_SYSTEM_AUDIO_ENABLED,
+                    Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED,
+                    Settings.Global.HTTP_PROXY,
+                    Settings.Global.INET_CONDITION_DEBOUNCE_DOWN_DELAY,
+                    Settings.Global.INET_CONDITION_DEBOUNCE_UP_DELAY,
+                    Settings.Global.INTENT_FIREWALL_UPDATE_CONTENT_URL,
+                    Settings.Global.INTENT_FIREWALL_UPDATE_METADATA_URL,
+                    Settings.Global.JOB_SCHEDULER_CONSTANTS,
+                    Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
+                    Settings.Global.LOCK_SOUND,
+                    Settings.Global.LOW_BATTERY_SOUND,
+                    Settings.Global.LOW_BATTERY_SOUND_TIMEOUT,
+                    Settings.Global.LOW_POWER_MODE,
+                    Settings.Global.LTE_SERVICE_FORCED,
+                    Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
+                    Settings.Global.MDC_INITIAL_MAX_RETRY,
+                    Settings.Global.MHL_INPUT_SWITCHING_ENABLED,
+                    Settings.Global.MHL_POWER_CHARGE_ENABLED,
+                    Settings.Global.MOBILE_DATA, // Candidate for backup?
+                    Settings.Global.MOBILE_DATA_ALWAYS_ON,
+                    Settings.Global.MODE_RINGER,
+                    Settings.Global.MULTI_SIM_DATA_CALL_SUBSCRIPTION,
+                    Settings.Global.MULTI_SIM_SMS_PROMPT,
+                    Settings.Global.MULTI_SIM_SMS_SUBSCRIPTION,
+                    Settings.Global.MULTI_SIM_VOICE_CALL_SUBSCRIPTION,
+                    Settings.Global.MULTI_SIM_VOICE_PROMPT,
+                    Settings.Global.NETSTATS_DEV_BUCKET_DURATION,
+                    Settings.Global.NETSTATS_DEV_DELETE_AGE,
+                    Settings.Global.NETSTATS_DEV_PERSIST_BYTES,
+                    Settings.Global.NETSTATS_DEV_ROTATE_AGE,
+                    Settings.Global.NETSTATS_ENABLED,
+                    Settings.Global.NETSTATS_GLOBAL_ALERT_BYTES,
+                    Settings.Global.NETSTATS_POLL_INTERVAL,
+                    Settings.Global.NETSTATS_SAMPLE_ENABLED,
+                    Settings.Global.NETSTATS_TIME_CACHE_MAX_AGE,
+                    Settings.Global.NETSTATS_UID_BUCKET_DURATION,
+                    Settings.Global.NETSTATS_UID_DELETE_AGE,
+                    Settings.Global.NETSTATS_UID_PERSIST_BYTES,
+                    Settings.Global.NETSTATS_UID_ROTATE_AGE,
+                    Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION,
+                    Settings.Global.NETSTATS_UID_TAG_DELETE_AGE,
+                    Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES,
+                    Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE,
+                    Settings.Global.NETWORK_AVOID_BAD_WIFI,
+                    Settings.Global.NETWORK_PREFERENCE,
+                    Settings.Global.NETWORK_RECOMMENDATION_REQUEST_TIMEOUT_MS,
+                    Settings.Global.NETWORK_SCORER_APP,
+                    Settings.Global.NETWORK_SCORING_PROVISIONED,
+                    Settings.Global.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT,
+                    Settings.Global.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS,
+                    Settings.Global.NEW_CONTACT_AGGREGATOR,
+                    Settings.Global.NITZ_UPDATE_DIFF,
+                    Settings.Global.NITZ_UPDATE_SPACING,
+                    Settings.Global.NSD_ON,
+                    Settings.Global.NTP_SERVER,
+                    Settings.Global.NTP_TIMEOUT,
+                    Settings.Global.OTA_DISABLE_AUTOMATIC_UPDATE,
+                    Settings.Global.OVERLAY_DISPLAY_DEVICES,
+                    Settings.Global.PAC_CHANGE_DELAY,
+                    Settings.Global.PACKAGE_VERIFIER_DEFAULT_RESPONSE,
+                    Settings.Global.PACKAGE_VERIFIER_ENABLE,
+                    Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB,
+                    Settings.Global.PACKAGE_VERIFIER_SETTING_VISIBLE,
+                    Settings.Global.PACKAGE_VERIFIER_TIMEOUT,
+                    Settings.Global.PDP_WATCHDOG_ERROR_POLL_COUNT,
+                    Settings.Global.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS,
+                    Settings.Global.PDP_WATCHDOG_LONG_POLL_INTERVAL_MS,
+                    Settings.Global.PDP_WATCHDOG_MAX_PDP_RESET_FAIL_COUNT,
+                    Settings.Global.PDP_WATCHDOG_POLL_INTERVAL_MS,
+                    Settings.Global.PDP_WATCHDOG_TRIGGER_PACKET_COUNT,
+                    Settings.Global.POLICY_CONTROL,
+                    Settings.Global.PREFERRED_NETWORK_MODE,
+                    Settings.Global.PROVISIONING_APN_ALARM_DELAY_IN_MS,
+                    Settings.Global.RADIO_BLUETOOTH,
+                    Settings.Global.RADIO_CELL,
+                    Settings.Global.RADIO_NFC,
+                    Settings.Global.RADIO_WIFI,
+                    Settings.Global.RADIO_WIMAX,
+                    Settings.Global.READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT,
+                    Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT,
+                    Settings.Global.RETAIL_DEMO_MODE_CONSTANTS,
+                    Settings.Global.SAFE_BOOT_DISALLOWED,
+                    Settings.Global.SAMPLING_PROFILER_MS,
+                    Settings.Global.SELINUX_STATUS,
+                    Settings.Global.SELINUX_UPDATE_CONTENT_URL,
+                    Settings.Global.SELINUX_UPDATE_METADATA_URL,
+                    Settings.Global.SEND_ACTION_APP_ERROR,
+                    Settings.Global.SET_GLOBAL_HTTP_PROXY,
+                    Settings.Global.SET_INSTALL_LOCATION,
+                    Settings.Global.SETUP_PREPAID_DATA_SERVICE_URL,
+                    Settings.Global.SETUP_PREPAID_DETECTION_REDIR_HOST,
+                    Settings.Global.SETUP_PREPAID_DETECTION_TARGET_URL,
+                    Settings.Global.SHORTCUT_MANAGER_CONSTANTS,
+                    Settings.Global.SHOW_TEMPERATURE_WARNING,
+                    Settings.Global.SMS_OUTGOING_CHECK_INTERVAL_MS,
+                    Settings.Global.SMS_OUTGOING_CHECK_MAX_COUNT,
+                    Settings.Global.SMS_SHORT_CODE_CONFIRMATION,
+                    Settings.Global.SMS_SHORT_CODE_RULE,
+                    Settings.Global.SMS_SHORT_CODES_UPDATE_CONTENT_URL,
+                    Settings.Global.SMS_SHORT_CODES_UPDATE_METADATA_URL,
+                    Settings.Global.STORAGE_BENCHMARK_INTERVAL,
+                    Settings.Global.SYNC_MAX_RETRY_DELAY_IN_SECONDS,
+                    Settings.Global.SYS_FREE_STORAGE_LOG_INTERVAL,
+                    Settings.Global.SYS_STORAGE_FULL_THRESHOLD_BYTES,
+                    Settings.Global.SYS_STORAGE_THRESHOLD_MAX_BYTES,
+                    Settings.Global.SYS_STORAGE_THRESHOLD_PERCENTAGE,
+                    Settings.Global.TCP_DEFAULT_INIT_RWND,
+                    Settings.Global.TETHER_DUN_APN,
+                    Settings.Global.TETHER_DUN_REQUIRED,
+                    Settings.Global.TETHER_SUPPORTED,
+                    Settings.Global.THEATER_MODE_ON,
+                    Settings.Global.TRANSITION_ANIMATION_SCALE,
+                    Settings.Global.TRUSTED_SOUND,
+                    Settings.Global.TZINFO_UPDATE_CONTENT_URL,
+                    Settings.Global.TZINFO_UPDATE_METADATA_URL,
+                    Settings.Global.UNINSTALLED_EPHEMERAL_APP_CACHE_DURATION_MILLIS,
+                    Settings.Global.UNLOCK_SOUND,
+                    Settings.Global.USE_GOOGLE_MAIL,
+                    Settings.Global.VT_IMS_ENABLED,
+                    Settings.Global.WAIT_FOR_DEBUGGER,
+                    Settings.Global.WARNING_TEMPERATURE,
+                    Settings.Global.WEBVIEW_DATA_REDUCTION_PROXY_KEY,
+                    Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED,
+                    Settings.Global.WEBVIEW_MULTIPROCESS,
+                    Settings.Global.WEBVIEW_PROVIDER,
+                    Settings.Global.WFC_IMS_ENABLED,
+                    Settings.Global.WFC_IMS_MODE,
+                    Settings.Global.WFC_IMS_ROAMING_ENABLED,
+                    Settings.Global.WFC_IMS_ROAMING_MODE,
+                    Settings.Global.WIFI_BOUNCE_DELAY_OVERRIDE_MS,
+                    Settings.Global.WIFI_COUNTRY_CODE,
+                    Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN,
+                    Settings.Global.WIFI_DISPLAY_CERTIFICATION_ON,
+                    Settings.Global.WIFI_DISPLAY_ON,
+                    Settings.Global.WIFI_DISPLAY_WPS_CONFIG,
+                    Settings.Global.WIFI_ENHANCED_AUTO_JOIN,
+                    Settings.Global.WIFI_EPHEMERAL_OUT_OF_RANGE_TIMEOUT_MS,
+                    Settings.Global.WIFI_FRAMEWORK_SCAN_INTERVAL_MS,
+                    Settings.Global.WIFI_FREQUENCY_BAND,
+                    Settings.Global.WIFI_IDLE_MS,
+                    Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT,
+                    Settings.Global.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS,
+                    Settings.Global.WIFI_NETWORK_SHOW_RSSI,
+                    Settings.Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,
+                    Settings.Global.WIFI_NUM_OPEN_NETWORKS_KEPT,
+                    Settings.Global.WIFI_ON,
+                    Settings.Global.WIFI_P2P_DEVICE_NAME,
+                    Settings.Global.WIFI_REENABLE_DELAY_MS,
+                    Settings.Global.WIFI_SAVED_STATE,
+                    Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE,
+                    Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS,
+                    Settings.Global.WIFI_SLEEP_POLICY,
+                    Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS,
+                    Settings.Global.WIFI_SUSPEND_OPTIMIZATIONS_ENABLED,
+                    Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED,
+                    Settings.Global.WIFI_WATCHDOG_ON,
+                    Settings.Global.WIMAX_NETWORKS_AVAILABLE_NOTIFICATION_ON,
+                    Settings.Global.WINDOW_ANIMATION_SCALE,
+                    Settings.Global.WIRELESS_CHARGING_STARTED_SOUND,
+                    Settings.Global.WTF_IS_FATAL,
+                    Settings.Global.ZEN_MODE,
+                    Settings.Global.ZEN_MODE_CONFIG_ETAG,
+                    Settings.Global.ZEN_MODE_RINGER_LEVEL);
+
+    private static final Set<String> BACKUP_BLACKLISTED_SECURE_SETTINGS =
+             newHashSet(
+                 Settings.Secure.ACCESSIBILITY_SCREEN_READER_URL,
+                 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
+                 Settings.Secure.ALLOWED_GEOLOCATION_ORIGINS,
+                 Settings.Secure.ALWAYS_ON_VPN_APP,
+                 Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN,
+                 Settings.Secure.ANDROID_ID,
+                 Settings.Secure.ANR_SHOW_BACKGROUND,
+                 Settings.Secure.ASSISTANT,
+                 Settings.Secure.ASSIST_DISCLOSURE_ENABLED,
+                 Settings.Secure.ASSIST_SCREENSHOT_ENABLED,
+                 Settings.Secure.ASSIST_STRUCTURE_ENABLED,
+                 Settings.Secure.AUTO_FILL_SERVICE,
+                 Settings.Secure.AUTOMATIC_STORAGE_MANAGER_BYTES_CLEARED,
+                 Settings.Secure.AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
+                 Settings.Secure.AUTOMATIC_STORAGE_MANAGER_DOWNLOADS_DAYS_TO_RETAIN,
+                 Settings.Secure.AUTOMATIC_STORAGE_MANAGER_ENABLED,
+                 Settings.Secure.AUTOMATIC_STORAGE_MANAGER_LAST_RUN,
+                 Settings.Secure.BACKUP_AUTO_RESTORE,
+                 Settings.Secure.BACKUP_ENABLED,
+                 Settings.Secure.BACKUP_PROVISIONED,
+                 Settings.Secure.BACKUP_TRANSPORT,
+                 Settings.Secure.BLUETOOTH_HCI_LOG,
+                 Settings.Secure.BRIGHTNESS_USE_TWILIGHT,  // Candidate for backup?
+                 Settings.Secure.CARRIER_APPS_HANDLED,
+                 Settings.Secure.COMPLETED_CATEGORY_PREFIX,
+                 Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS,
+                 Settings.Secure.DEFAULT_INPUT_METHOD,
+                 Settings.Secure.DEMO_USER_SETUP_COMPLETE,
+                 Settings.Secure.DEVICE_PAIRED,
+                 Settings.Secure.DIALER_DEFAULT_APPLICATION,
+                 Settings.Secure.DISABLED_PRINT_SERVICES,
+                 Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS,
+                 Settings.Secure.DISPLAY_DENSITY_FORCED,
+                 Settings.Secure.DOWNLOADS_BACKUP_ALLOW_METERED,  // Candidate?
+                 Settings.Secure.DOWNLOADS_BACKUP_CHARGING_ONLY, // Candidate?
+                 Settings.Secure.DOWNLOADS_BACKUP_ENABLED, // Candidate?
+                 Settings.Secure.DOZE_ALWAYS_ON,
+                 Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION,
+                 Settings.Secure.ENABLED_NOTIFICATION_ASSISTANT,
+                 Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES,
+                 Settings.Secure.ENABLED_PRINT_SERVICES,
+                 Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS,
+                 Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR,
+                 Settings.Secure.INPUT_METHOD_SELECTOR_VISIBILITY,
+                 Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY,
+                 Settings.Secure.INSTALL_NON_MARKET_APPS,
+                 Settings.Secure.LAST_SETUP_SHOWN,
+                 Settings.Secure.LOCATION_MODE,
+                 Settings.Secure.LOCATION_PREVIOUS_MODE,
+                 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, // Candidate?
+                 Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT, // Candidate?
+                 Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
+                 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, // Candidate?
+                 Settings.Secure.LOCK_TO_APP_EXIT_LOCKED,
+                 Settings.Secure.MANAGED_PROFILE_CONTACT_REMOTE_SEARCH,
+                 Settings.Secure.MULTI_PRESS_TIMEOUT,
+                 Settings.Secure.NFC_PAYMENT_FOREGROUND,
+                 Settings.Secure.PACKAGE_VERIFIER_STATE,
+                 Settings.Secure.PACKAGE_VERIFIER_USER_CONSENT,
+                 Settings.Secure.PARENTAL_CONTROL_LAST_UPDATE,
+                 Settings.Secure.PAYMENT_SERVICE_SEARCH_URI,
+                 Settings.Secure.PRINT_SERVICE_SEARCH_URI,
+                 Settings.Secure.SCREENSAVER_ACTIVATE_ON_DOCK, // Candidate?
+                 Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, // Candidate?
+                 Settings.Secure.SCREENSAVER_COMPONENTS,
+                 Settings.Secure.SCREENSAVER_DEFAULT_COMPONENT, // Candidate?
+                 Settings.Secure.SCREENSAVER_ENABLED, // Candidate?
+                 Settings.Secure.SEARCH_GLOBAL_SEARCH_ACTIVITY,
+                 Settings.Secure.SEARCH_MAX_RESULTS_PER_SOURCE,
+                 Settings.Secure.SEARCH_MAX_RESULTS_TO_DISPLAY,
+                 Settings.Secure.SEARCH_MAX_SHORTCUTS_RETURNED,
+                 Settings.Secure.SEARCH_MAX_SOURCE_EVENT_AGE_MILLIS,
+                 Settings.Secure.SEARCH_MAX_STAT_AGE_MILLIS,
+                 Settings.Secure.SEARCH_MIN_CLICKS_FOR_SOURCE_RANKING,
+                 Settings.Secure.SEARCH_MIN_IMPRESSIONS_FOR_SOURCE_RANKING,
+                 Settings.Secure.SEARCH_NUM_PROMOTED_SOURCES,
+                 Settings.Secure.SEARCH_PER_SOURCE_CONCURRENT_QUERY_LIMIT,
+                 Settings.Secure.SEARCH_PREFILL_MILLIS,
+                 Settings.Secure.SEARCH_PROMOTED_SOURCE_DEADLINE_MILLIS,
+                 Settings.Secure.SEARCH_QUERY_THREAD_CORE_POOL_SIZE,
+                 Settings.Secure.SEARCH_QUERY_THREAD_MAX_POOL_SIZE,
+                 Settings.Secure.SEARCH_SHORTCUT_REFRESH_CORE_POOL_SIZE,
+                 Settings.Secure.SEARCH_SHORTCUT_REFRESH_MAX_POOL_SIZE,
+                 Settings.Secure.SEARCH_SOURCE_TIMEOUT_MILLIS,
+                 Settings.Secure.SEARCH_THREAD_KEEPALIVE_SECONDS,
+                 Settings.Secure.SEARCH_WEB_RESULTS_OVERRIDE_LIMIT,
+                 Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE,
+                 Settings.Secure.SETTINGS_CLASSNAME,
+                 Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, // candidate?
+                 Settings.Secure.SKIP_FIRST_USE_HINTS, // candidate?
+                 Settings.Secure.SMS_DEFAULT_APPLICATION,
+                 Settings.Secure.TRUST_AGENTS_INITIALIZED,
+                 Settings.Secure.TV_INPUT_CUSTOM_LABELS,
+                 Settings.Secure.TV_INPUT_HIDDEN_INPUTS,
+                 Settings.Secure.UI_NIGHT_MODE, // candidate?
+                 Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS,
+                 Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED,
+                 Settings.Secure.USER_SETUP_COMPLETE,
+                 Settings.Secure.VOICE_INTERACTION_SERVICE,
+                 Settings.Secure.VOICE_RECOGNITION_SERVICE,
+                 Settings.Secure.VR_DISPLAY_MODE, // Candidate?
+                 Settings.Secure.WEB_ACTION_ENABLED);
+
+    @Test
+    public void systemSettingsBackedUpOrBlacklisted() {
+        checkSettingsBackedUpOrBlacklisted(
+                getCandidateSettings(Settings.System.class),
+                newHashSet(Settings.System.SETTINGS_TO_BACKUP),
+                BACKUP_BLACKLISTED_SYSTEM_SETTINGS);
+    }
+
+    @Test
+    public void globalSettingsBackedUpOrBlacklisted() {
+        checkSettingsBackedUpOrBlacklisted(
+            getCandidateSettings(Settings.Global.class),
+            newHashSet(Settings.Global.SETTINGS_TO_BACKUP),
+            BACKUP_BLACKLISTED_GLOBAL_SETTINGS);
+    }
+
+    @Test
+    public void secureSettingsBackedUpOrBlacklisted() {
+        checkSettingsBackedUpOrBlacklisted(
+                getCandidateSettings(Settings.Secure.class),
+                newHashSet(Settings.Secure.SETTINGS_TO_BACKUP),
+            BACKUP_BLACKLISTED_SECURE_SETTINGS);
+    }
+
+    private static void checkSettingsBackedUpOrBlacklisted(
+            Set<String> settings, Set<String> settingsToBackup, Set<String> blacklist) {
+        Set<String> settingsNotBackedUp = difference(settings, settingsToBackup);
+        Set<String> settingsNotBackedUpOrBlacklisted = difference(settingsNotBackedUp, blacklist);
+        assertThat(
+                "Settings not backed up or blacklisted",
+                settingsNotBackedUpOrBlacklisted,
+                is(empty()));
+
+        assertThat(
+            "blacklisted settings backed up",
+            intersect(settingsToBackup, blacklist),
+            is(empty()));
+    }
+
+    private static Set<String> getCandidateSettings(Class<? extends Settings.NameValueTable> clazz) {
+        HashSet<String> result = new HashSet<String>();
+        for (Field field : clazz.getDeclaredFields()) {
+            if (looksLikeValidSetting(field)) {
+                try {
+                    result.add((String) field.get(null));
+                } catch (IllegalAccessException e) {
+                    // Impossible for public fields
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+        return result;
+    }
+
+    private static boolean looksLikeValidSetting(Field field) {
+        int modifiers = field.getModifiers();
+        return isPublic(modifiers)
+                && isStatic(modifiers)
+                && isFinal(modifiers)
+                && field.getType() == String.class
+                && field.getAnnotation(Deprecated.class) == null;
+    }
+
+    private static <T> Set<T> difference(Set<T> s1, Set<T> s2) {
+        HashSet<T> result = new HashSet<T>(s1);
+        result.removeAll(s2);
+        return result;
+    }
+
+    private static <T> Set<T> intersect(Set<T> s1, Set<T> s2) {
+        HashSet<T> result = new HashSet<T>(s1);
+        result.retainAll(s2);
+        return result;
+    }
+
+}
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
index 97ea885..d89dc63 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
@@ -81,35 +81,23 @@
     public void testVoiceImes() throws Exception {
         // locale: en_US
         assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_EN_US,
-                !IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme");
+                "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme");
         assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_US,
-                !IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme");
-        assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_EN_US,
-                IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme");
-        assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_US,
-                IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0",
+                "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0",
                 "DummyNonDefaultAutoVoiceIme1");
 
         // locale: en_GB
         assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_EN_GB,
-                !IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme");
+                "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme");
         assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_GB,
-                !IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme");
-        assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_EN_GB,
-                IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme");
-        assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_GB,
-                IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0",
+                "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0",
                 "DummyNonDefaultAutoVoiceIme1");
 
         // locale: ja_JP
         assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_JA_JP,
-                !IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme");
+                "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme");
         assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_JA_JP,
-                !IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme");
-        assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_JA_JP,
-                IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme");
-        assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_JA_JP,
-                IS_SYSTEM_READY, "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0",
+                "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0",
                 "DummyNonDefaultAutoVoiceIme1");
     }
 
@@ -117,54 +105,35 @@
     public void testKeyboardImes() throws Exception {
         // locale: en_US
         assertDefaultEnabledImes(getSamplePreinstalledImes("en-rUS"), LOCALE_EN_US,
-                !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin");
-        assertDefaultEnabledImes(getSamplePreinstalledImes("en-rUS"), LOCALE_EN_US,
-                IS_SYSTEM_READY, "com.android.apps.inputmethod.latin",
-                "com.android.apps.inputmethod.voice");
+                "com.android.apps.inputmethod.latin", "com.android.apps.inputmethod.voice");
 
         // locale: en_GB
         assertDefaultEnabledImes(getSamplePreinstalledImes("en-rGB"), LOCALE_EN_GB,
-                !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin");
-        assertDefaultEnabledImes(getSamplePreinstalledImes("en-rGB"), LOCALE_EN_GB,
-                IS_SYSTEM_READY, "com.android.apps.inputmethod.latin",
-                "com.android.apps.inputmethod.voice");
+                "com.android.apps.inputmethod.latin", "com.android.apps.inputmethod.voice");
 
         // locale: en_IN
         assertDefaultEnabledImes(getSamplePreinstalledImes("en-rIN"), LOCALE_EN_IN,
-                !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin");
-        assertDefaultEnabledImes(getSamplePreinstalledImes("en-rIN"), LOCALE_EN_IN,
-                IS_SYSTEM_READY, "com.android.apps.inputmethod.hindi",
+                "com.android.apps.inputmethod.hindi",
                 "com.android.apps.inputmethod.latin", "com.android.apps.inputmethod.voice");
 
         // locale: hi
         assertDefaultEnabledImes(getSamplePreinstalledImes("hi"), LOCALE_HI,
-                !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin");
-        assertDefaultEnabledImes(getSamplePreinstalledImes("hi"), LOCALE_HI,
-                IS_SYSTEM_READY, "com.android.apps.inputmethod.hindi",
-                "com.android.apps.inputmethod.latin", "com.android.apps.inputmethod.voice");
+                "com.android.apps.inputmethod.hindi", "com.android.apps.inputmethod.latin",
+                "com.android.apps.inputmethod.voice");
 
         // locale: ja_JP
         assertDefaultEnabledImes(getSamplePreinstalledImes("ja-rJP"), LOCALE_JA_JP,
-                !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin");
-        assertDefaultEnabledImes(getSamplePreinstalledImes("ja-rJP"), LOCALE_JA_JP,
-                IS_SYSTEM_READY, "com.android.apps.inputmethod.japanese",
-                "com.android.apps.inputmethod.voice");
+                "com.android.apps.inputmethod.japanese", "com.android.apps.inputmethod.voice");
 
         // locale: zh_CN
         assertDefaultEnabledImes(getSamplePreinstalledImes("zh-rCN"), LOCALE_ZH_CN,
-                !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin");
-        assertDefaultEnabledImes(getSamplePreinstalledImes("zh-rCN"), LOCALE_ZH_CN,
-                IS_SYSTEM_READY, "com.android.apps.inputmethod.pinyin",
-                "com.android.apps.inputmethod.voice");
+                "com.android.apps.inputmethod.pinyin", "com.android.apps.inputmethod.voice");
 
         // locale: zh_TW
         // Note: In this case, no IME is suitable for the system locale. Hence we will pick up a
         // fallback IME regardless of the "default" attribute.
         assertDefaultEnabledImes(getSamplePreinstalledImes("zh-rTW"), LOCALE_ZH_TW,
-                !IS_SYSTEM_READY, "com.android.apps.inputmethod.latin");
-        assertDefaultEnabledImes(getSamplePreinstalledImes("zh-rTW"), LOCALE_ZH_TW,
-                IS_SYSTEM_READY, "com.android.apps.inputmethod.latin",
-                "com.android.apps.inputmethod.voice");
+                "com.android.apps.inputmethod.latin", "com.android.apps.inputmethod.voice");
     }
 
     @SmallTest
@@ -792,10 +761,10 @@
     }
 
     private void assertDefaultEnabledImes(final ArrayList<InputMethodInfo> preinstalledImes,
-            final Locale systemLocale, final boolean isSystemReady, String... expectedImeNames) {
+            final Locale systemLocale, String... expectedImeNames) {
         final Context context = createTargetContextWithLocales(new LocaleList(systemLocale));
         final String[] actualImeNames = getPackageNames(
-                InputMethodUtils.getDefaultEnabledImes(context, isSystemReady, preinstalledImes));
+                InputMethodUtils.getDefaultEnabledImes(context, preinstalledImes));
         assertEquals(expectedImeNames.length, actualImeNames.length);
         for (int i = 0; i < expectedImeNames.length; ++i) {
             assertEquals(expectedImeNames[i], actualImeNames[i]);
diff --git a/core/tests/coretests/src/com/android/internal/logging/legacy/CounterParserTest.java b/core/tests/coretests/src/com/android/internal/logging/legacy/CounterParserTest.java
deleted file mode 100644
index 5a7766b..0000000
--- a/core/tests/coretests/src/com/android/internal/logging/legacy/CounterParserTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-
-public class CounterParserTest extends ParserTest {
-
-    public CounterParserTest() {
-        mParser = new CounterParser();
-    }
-
-    public void testGoodData() throws Throwable {
-        String name = "foo";
-        int value = 5;
-        Object[] objects = new Object[2];
-        objects[0] = name;
-        objects[1] = value;
-
-        validateGoodData(name, value, objects);
-    }
-
-    private void validateGoodData(String name, int value, Object[] objects) {
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, times(1)).incrementBy(mNameCaptor.capture(), mCountCaptor.capture());
-
-        assertEquals(TronCounters.TRON_AOSP_PREFIX + name, mNameCaptor.getValue());
-        assertEquals(value, mCountCaptor.getValue().intValue());
-    }
-
-    public void testMissingName() throws Throwable {
-        Object[] objects = new Object[1];
-        objects[0] = 5;
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).incrementBy(anyString(), anyInt());
-    }
-
-    public void testWrongTypes() throws Throwable {
-        String name = "foo";
-        int value = 5;
-        Object[] objects = new Object[2];
-        objects[0] = value;
-        objects[1] = name;
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).incrementBy(anyString(), anyInt());
-    }
-
-    public void testIgnoreMissingInput() throws Throwable {
-        Object[] objects = new Object[0];
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).incrementBy(anyString(), anyInt());
-    }
-
-    public void testIgnoreUnexpectedData() throws Throwable {
-        String name = "foo";
-        int value = 5;
-        Object[] objects = new Object[3];
-        objects[0] = name;
-        objects[1] = value;
-        objects[2] = "foo";
-
-        validateGoodData(name, value, objects);
-    }
-
-
-}
diff --git a/core/tests/coretests/src/com/android/internal/logging/legacy/HistogramParserTest.java b/core/tests/coretests/src/com/android/internal/logging/legacy/HistogramParserTest.java
deleted file mode 100644
index 1bd9d83..0000000
--- a/core/tests/coretests/src/com/android/internal/logging/legacy/HistogramParserTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-
-public class HistogramParserTest extends ParserTest {
-
-    public HistogramParserTest() {
-        mParser = new HistogramParser();
-    }
-
-    public void testGoodData() throws Throwable {
-        String name = "foo";
-        int bucket = 5;
-        Object[] objects = new Object[2];
-        objects[0] = name;
-        objects[1] = bucket;
-
-        validateGoodData(name, bucket, objects);
-    }
-
-    private void validateGoodData(String name, int bucket, Object[] objects) {
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, times(1))
-                .incrementIntHistogram(mNameCaptor.capture(), mCountCaptor.capture());
-
-        assertEquals(TronCounters.TRON_AOSP_PREFIX + name, mNameCaptor.getValue());
-        assertEquals(bucket, mCountCaptor.getValue().intValue());
-    }
-
-    public void testMissingName() throws Throwable {
-        Object[] objects = new Object[1];
-        objects[0] = 5;
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).incrementBy(anyString(), anyInt());
-    }
-
-    public void testWrongTypes() throws Throwable {
-        String name = "foo";
-        int value = 5;
-        Object[] objects = new Object[2];
-        objects[0] = value;
-        objects[1] = name;
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).incrementBy(anyString(), anyInt());
-    }
-
-    public void testIgnoreMissingInput() throws Throwable {
-        Object[] objects = new Object[0];
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).incrementBy(anyString(), anyInt());
-    }
-
-    public void testIgnoreUnexpectedData() throws Throwable {
-        String name = "foo";
-        int bucket = 5;
-        Object[] objects = new Object[3];
-        objects[0] = name;
-        objects[1] = bucket;
-        objects[2] = "foo";
-
-        validateGoodData(name, bucket, objects);
-    }
-}
diff --git a/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationActionClickedParserTest.java b/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationActionClickedParserTest.java
deleted file mode 100644
index f05205d..0000000
--- a/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationActionClickedParserTest.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import static org.mockito.Matchers.anyObject;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-public class NotificationActionClickedParserTest extends ParserTest {
-
-    public NotificationActionClickedParserTest() {
-        mParser = new NotificationActionClickedParser();
-    }
-
-    public void testGoodData() throws Throwable {
-        int t = 1000;
-        int index = 1;
-        Object[] objects = new Object[2];
-        objects[0] = mKey;
-        objects[1] = index;
-
-        validateGoodData(t, "", index, objects);
-    }
-
-    public void testTagged() throws Throwable {
-        int t = 1000;
-        int index = 1;
-        Object[] objects = new Object[2];
-        objects[0] = mTaggedKey;
-        objects[1] = index;
-
-        validateGoodData(t, mTag, index, objects);
-    }
-
-    private LogMaker validateGoodData(int t, String tag, int index, Object[] objects) {
-        mParser.parseEvent(mLogger, t, objects);
-
-        verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
-
-        LogMaker proto = mProtoCaptor.getValue();
-        assertEquals(t, proto.getTimestamp());
-        assertEquals(MetricsEvent.NOTIFICATION_ITEM_ACTION, proto.getCategory());
-        assertEquals(mKeyPackage, proto.getPackageName());
-        validateNotificationIdAndTag(proto, mId, tag);
-        assertEquals(MetricsEvent.TYPE_ACTION, proto.getType());
-        assertEquals(index, proto.getSubtype());
-        return proto;
-    }
-
-    public void testMissingData() throws Throwable {
-        Object[] objects = new Object[0];
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-    }
-
-    public void testWrongType() throws Throwable {
-        Object[] objects = new Object[2];
-        objects[0] = 2;
-        objects[1] = 5;
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-    }
-
-    public void testBadKey() throws Throwable {
-        Object[] objects = new Object[2];
-        objects[0] = "foo";
-        objects[1] = 5;
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-    }
-
-    public void testMncTimestamps() throws Throwable {
-        int t = 1000;
-        int index = 1;
-        Object[] objects = new Object[5];
-        objects[0] = mKey;
-        objects[1] = index;
-        objects[2] = mSinceCreationMillis;
-        objects[3] = mSinceUpdateMillis;
-        objects[4] = mSinceVisibleMillis;
-
-        LogMaker proto = validateGoodData(t, "", index, objects);
-        validateNotificationTimes(proto, mSinceCreationMillis, mSinceUpdateMillis,
-                mSinceVisibleMillis);
-    }
-
-    public void testIgnoreUnexpectedData() throws Throwable {
-        int t = 1000;
-        int index = 1;
-        Object[] objects = new Object[6];
-        objects[0] = mKey;
-        objects[1] = index;
-        objects[2] = mSinceCreationMillis;
-        objects[3] = mSinceUpdateMillis;
-        objects[4] = mSinceVisibleMillis;
-        objects[5] = "foo";
-
-        validateGoodData(t, "", index, objects);
-    }
-}
diff --git a/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationAlertParserTest.java b/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationAlertParserTest.java
deleted file mode 100644
index 7771e84..0000000
--- a/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationAlertParserTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-import org.mockito.ArgumentCaptor;
-
-public class NotificationAlertParserTest extends ParserTest {
-    protected ArgumentCaptor<Boolean> mConfigCaptor;
-
-    private final int mTime = 1000;
-
-    public NotificationAlertParserTest() {
-        mParser = new NotificationAlertParser();
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mConfigCaptor = ArgumentCaptor.forClass(Boolean.class);
-        when(mLogger.getConfig(anyString())).thenReturn(false);
-    }
-
-    public void testBuzzOnly() throws Throwable {
-        Object[] objects = new Object[4];
-        objects[0] = mTaggedKey;
-        objects[1] = 1;
-        objects[2] = 0;
-        objects[3] = 0;
-
-        validateInteraction(true, false, false, objects);
-    }
-
-    public void testBeepOnly() throws Throwable {
-        Object[] objects = new Object[4];
-        objects[0] = mTaggedKey;
-        objects[1] = 0;
-        objects[2] = 1;
-        objects[3] = 0;
-
-        validateInteraction(false, true, false, objects);
-    }
-
-    public void testBlinkOnly() throws Throwable {
-        Object[] objects = new Object[4];
-        objects[0] = mTaggedKey;
-        objects[1] = 0;
-        objects[2] = 0;
-        objects[3] = 1;
-
-        validateInteraction(false, false, true, objects);
-    }
-
-    public void testBuzzBlink() throws Throwable {
-        Object[] objects = new Object[4];
-        objects[0] = mTaggedKey;
-        objects[1] = 1;
-        objects[2] = 0;
-        objects[3] = 1;
-
-        validateInteraction(true, false, true, objects);
-    }
-
-    public void testBeepBlink() throws Throwable {
-        Object[] objects = new Object[4];
-        objects[0] = mTaggedKey;
-        objects[1] = 0;
-        objects[2] = 1;
-        objects[3] = 1;
-
-        validateInteraction(false, true, true, objects);
-    }
-
-    public void testIgnoreExtraArgs() throws Throwable {
-        Object[] objects = new Object[5];
-        objects[0] = mTaggedKey;
-        objects[1] = 0;
-        objects[2] = 1;
-        objects[3] = 1;
-        objects[4] = "foo";
-
-        validateInteraction(false, true, true, objects);
-    }
-
-    private void validateInteraction(boolean buzz, boolean beep, boolean blink, Object[] objects) {
-        int flags = 0;
-        int counts = 0;
-        if (buzz) {
-            counts++;
-            flags |= NotificationAlertParser.BUZZ;
-        }
-        if (beep) {
-            counts++;
-            flags |= NotificationAlertParser.BEEP;
-        }
-        if (blink) {
-            counts++;
-            flags |= NotificationAlertParser.BLINK;
-        }
-
-        mParser.parseEvent(mLogger, mTime, objects);
-
-        verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
-
-        LogMaker proto = mProtoCaptor.getValue();
-        assertEquals(mTime, proto.getTimestamp());
-        assertEquals(MetricsEvent.NOTIFICATION_ALERT, proto.getCategory());
-        assertEquals(mKeyPackage, proto.getPackageName());
-        validateNotificationIdAndTag(proto, mId, mTag);
-        assertEquals(flags, proto.getSubtype());
-        assertEquals(MetricsEvent.TYPE_OPEN, proto.getType());
-
-    }
-}
diff --git a/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationCanceledParserTest.java b/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationCanceledParserTest.java
deleted file mode 100644
index 77b2ed6..0000000
--- a/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationCanceledParserTest.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import static org.mockito.Mockito.anyObject;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-public class NotificationCanceledParserTest extends ParserTest {
-
-    public NotificationCanceledParserTest() {
-        mParser = new NotificationCanceledParser();
-    }
-
-    public void testGoodProto() throws Throwable {
-        int t = 1000;
-        int reason = NotificationCanceledParser.REASON_DELEGATE_CANCEL;
-        Object[] objects = new Object[2];
-        objects[0] = mKey;
-        objects[1] = reason;
-
-        validateGoodData(t, "", reason, objects);
-    }
-
-    public void testTagged() throws Throwable {
-        int t = 1000;
-        int reason = NotificationCanceledParser.REASON_DELEGATE_CANCEL;
-        Object[] objects = new Object[2];
-        objects[0] = mTaggedKey;
-        objects[1] = reason;
-
-        validateGoodData(t, mTag, reason, objects);
-    }
-
-    private void validateGoodData(int t, String tag, int reason, Object[] objects) {
-        mParser.parseEvent(mLogger, t, objects);
-
-        verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
-
-        LogMaker proto = mProtoCaptor.getValue();
-        assertEquals(t, proto.getTimestamp());
-        assertEquals(MetricsEvent.NOTIFICATION_ITEM, proto.getCategory());
-        assertEquals(mKeyPackage, proto.getPackageName());
-        validateNotificationIdAndTag(proto, mId, tag);
-        assertEquals(MetricsEvent.TYPE_DISMISS, proto.getType());
-        assertEquals(reason, proto.getSubtype());
-    }
-
-    public void testLifetime() throws Throwable {
-        int t = 1000;
-        int reason = NotificationCanceledParser.REASON_DELEGATE_CANCEL;
-        Object[] objects = new Object[3];
-        objects[0] = mKey;
-        objects[1] = reason;
-        objects[2] = mSinceCreationMillis;
-
-        validateTimers(t, objects, mSinceCreationMillis, 0, 0);
-    }
-
-    public void testExposure() throws Throwable {
-        int t = 1000;
-        int reason = NotificationCanceledParser.REASON_DELEGATE_CANCEL;
-        Object[] objects = new Object[4];
-        objects[0] = mKey;
-        objects[1] = reason;
-        objects[2] = mSinceCreationMillis;
-        objects[3] = mSinceVisibleMillis;
-
-
-        validateTimers(t, objects, mSinceCreationMillis, 0, mSinceVisibleMillis);
-    }
-
-    public void testFreshness() throws Throwable {
-        int t = 1000;
-        int reason = NotificationCanceledParser.REASON_DELEGATE_CANCEL;
-        Object[] objects = new Object[5];
-        objects[0] = mKey;
-        objects[1] = reason;
-        objects[2] = mSinceCreationMillis;
-        objects[3] = mSinceUpdateMillis;
-        objects[4] = mSinceVisibleMillis;
-
-        validateTimers(t, objects, mSinceCreationMillis, mSinceUpdateMillis, mSinceVisibleMillis);
-    }
-
-    private void validateTimers(int t, Object[] objects, int life, int freshness, int exposure) {
-        mParser.parseEvent(mLogger, t, objects);
-
-        verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
-
-        LogMaker proto = mProtoCaptor.getValue();
-        validateNotificationTimes(proto, life, freshness, exposure);
-    }
-
-    public void verifyReason(int reason, boolean intentional, boolean important, String counter)
-            throws Throwable {
-        Object[] objects = new Object[2];
-        objects[0] = mKey;
-        objects[1] = reason;
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        if (intentional) {
-            verify(mLogger, times(1)).addEvent((LogMaker) anyObject());
-        }
-    }
-
-    public void testDelegateCancel() throws Throwable {
-        verifyReason(NotificationCanceledParser.REASON_DELEGATE_CANCEL,
-                true, true, TronCounters.TRON_NOTE_DISMISS_BY_USER);
-    }
-
-    public void testDelegateCancelAll() throws Throwable {
-        verifyReason(NotificationCanceledParser.REASON_DELEGATE_CANCEL_ALL,
-                true, true, TronCounters.TRON_NOTE_DISMISS_BY_USER);
-    }
-
-    public void testListenerCancel() throws Throwable {
-        verifyReason(NotificationCanceledParser.REASON_LISTENER_CANCEL,
-                false, true, TronCounters.TRON_NOTE_DISMISS_BY_LISTENER);
-    }
-
-    public void testListenerCancelAll() throws Throwable {
-        verifyReason(NotificationCanceledParser.REASON_LISTENER_CANCEL_ALL,
-                false, true, TronCounters.TRON_NOTE_DISMISS_BY_LISTENER);
-    }
-
-    public void testDelegateClick() throws Throwable {
-        verifyReason(NotificationCanceledParser.REASON_DELEGATE_CLICK,
-                true, true, TronCounters.TRON_NOTE_DISMISS_BY_CLICK);
-    }
-
-    public void testBanned() throws Throwable {
-        verifyReason(NotificationCanceledParser.REASON_PACKAGE_BANNED,
-                false, true, TronCounters.TRON_NOTE_DISMISS_BY_BAN);
-    }
-
-    public void testUnknownReason() throws Throwable {
-        verifyReason(1001010, false, false, TronCounters.TRON_NOTE_DISMISS_BY_BAN);
-    }
-
-    public void testMissingData() throws Throwable {
-        Object[] objects = new Object[0];
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-    }
-
-    public void testWrongType() throws Throwable {
-        Object[] objects = new Object[2];
-        objects[0] = 2;
-        objects[1] = 5;
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-    }
-
-    public void testBadKey() throws Throwable {
-        Object[] objects = new Object[2];
-        objects[0] = "foo";
-        objects[1] = 5;
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-    }
-
-    public void testIgnoreUnexpectedData() throws Throwable {
-        int t = 1000;
-        int reason = NotificationCanceledParser.REASON_DELEGATE_CANCEL;
-        Object[] objects = new Object[3];
-        objects[0] = mKey;
-        objects[1] = reason;
-        objects[2] = "foo";
-
-        validateGoodData(t, "", reason, objects);
-    }
-}
diff --git a/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationClickedParserTest.java b/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationClickedParserTest.java
deleted file mode 100644
index cc65132..0000000
--- a/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationClickedParserTest.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import static org.mockito.Matchers.anyObject;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-public class NotificationClickedParserTest extends ParserTest {
-
-    public NotificationClickedParserTest() {
-        mParser = new NotificationClickedParser();
-    }
-
-    public void testGoodData() throws Throwable {
-        int t = 1000;
-        Object[] objects = new Object[1];
-        objects[0] = mKey;
-
-        validateGoodData(t, "", objects);
-    }
-
-    public void testTagged() throws Throwable {
-        int t = 1000;
-        Object[] objects = new Object[1];
-        objects[0] = mTaggedKey;
-
-        validateGoodData(t, mTag, objects);
-    }
-
-    private LogMaker validateGoodData(int t, String tag, Object[] objects) {
-        mParser.parseEvent(mLogger, t, objects);
-
-        verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
-
-        LogMaker proto = mProtoCaptor.getValue();
-        assertEquals(t, proto.getTimestamp());
-        assertEquals(MetricsEvent.NOTIFICATION_ITEM, proto.getCategory());
-        assertEquals(mKeyPackage, proto.getPackageName());
-        validateNotificationIdAndTag(proto, mId, tag);
-        assertEquals(MetricsEvent.TYPE_ACTION, proto.getType());
-        assertEquals(0, proto.getSubtype());
-        return proto;
-    }
-
-    public void testMissingKey() throws Throwable {
-        Object[] objects = new Object[0];
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-    }
-
-    public void testWrongType() throws Throwable {
-        Object[] objects = new Object[1];
-        objects[0] = 5;
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-    }
-
-    public void testBadKey() throws Throwable {
-        Object[] objects = new Object[1];
-        objects[0] = "foo";
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-    }
-
-    public void testMncTimestamps() throws Throwable {
-        int t = 1000;
-        Object[] objects = new Object[4];
-        objects[0] = mKey;
-        objects[1] = mSinceCreationMillis;
-        objects[2] = mSinceUpdateMillis;
-        objects[3] = mSinceVisibleMillis;
-
-        LogMaker proto = validateGoodData(t, "", objects);
-        validateNotificationTimes(proto, mSinceCreationMillis, mSinceUpdateMillis,
-                mSinceVisibleMillis);
-    }
-
-    public void testIgnoreUnexpectedData() throws Throwable {
-        int t = 1000;
-        Object[] objects = new Object[5];
-        objects[0] = mKey;
-        objects[1] = mSinceCreationMillis;
-        objects[2] = mSinceUpdateMillis;
-        objects[3] = mSinceVisibleMillis;
-        objects[4] = "foo";
-
-        validateGoodData(t, "", objects);
-    }
-}
diff --git a/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationExpansionParserTest.java b/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationExpansionParserTest.java
deleted file mode 100644
index f337f91..0000000
--- a/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationExpansionParserTest.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import static org.mockito.Matchers.anyObject;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-public class NotificationExpansionParserTest extends ParserTest {
-
-    public NotificationExpansionParserTest() {
-        mParser = new NotificationExpansionParser();
-    }
-
-    public void testExpandedByUser() throws Throwable {
-        int t = 1000;
-        int byUser = 1;
-        int expanded = 1;
-        Object[] objects = new Object[3];
-        objects[0] = mKey;
-        objects[1] = byUser;
-        objects[2] = expanded;
-
-        validateGoodData(t, "", objects);
-    }
-
-    public void testTagged() throws Throwable {
-        int t = 1000;
-        int byUser = 1;
-        int expanded = 1;
-        Object[] objects = new Object[3];
-        objects[0] = mTaggedKey;
-        objects[1] = byUser;
-        objects[2] = expanded;
-
-        validateGoodData(t, mTag, objects);
-    }
-
-    private LogMaker validateGoodData(int t, String tag, Object[] objects) {
-        mParser.parseEvent(mLogger, t, objects);
-
-        verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
-
-        LogMaker proto = mProtoCaptor.getValue();
-        assertEquals(t, proto.getTimestamp());
-        assertEquals(MetricsEvent.NOTIFICATION_ITEM, proto.getCategory());
-        assertEquals(mKeyPackage, proto.getPackageName());
-        validateNotificationIdAndTag(proto, mId, tag);
-        assertEquals(MetricsEvent.TYPE_DETAIL, proto.getType());
-        return proto;
-    }
-
-    public void testAutoExpand() throws Throwable {
-        int t = 1000;
-        int byUser = 0;
-        int expanded = 1;
-        Object[] objects = new Object[3];
-        objects[0] = mKey;
-        objects[1] = byUser;
-        objects[2] = expanded;
-
-        mParser.parseEvent(mLogger, t, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-    }
-
-    public void testCollapsedByUser() throws Throwable {
-        int t = 1000;
-        int byUser = 1;
-        int expanded = 0;
-        Object[] objects = new Object[3];
-        objects[0] = mKey;
-        objects[1] = byUser;
-        objects[2] = expanded;
-
-        mParser.parseEvent(mLogger, t, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-    }
-
-    public void testAutoCollapsed() throws Throwable {
-        int t = 1000;
-        int byUser = 0;
-        int expanded = 0;
-        Object[] objects = new Object[3];
-        objects[0] = mKey;
-        objects[1] = byUser;
-        objects[2] = expanded;
-
-        mParser.parseEvent(mLogger, t, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-    }
-
-    public void testMissingData() throws Throwable {
-        Object[] objects = new Object[0];
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-    }
-
-    public void testWrongType() throws Throwable {
-        Object[] objects = new Object[3];
-        objects[0] = 2;
-        objects[1] = 5;
-        objects[2] = 7;
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-    }
-
-    public void testBadKey() throws Throwable {
-        Object[] objects = new Object[3];
-        objects[0] = "foo";
-        objects[1] = 5;
-        objects[2] = 2;
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-    }
-
-    public void testMncTimestamps() throws Throwable {
-        int t = 1000;
-        int byUser = 1;
-        int expanded = 1;
-        Object[] objects = new Object[6];
-        objects[0] = mKey;
-        objects[1] = byUser;
-        objects[2] = expanded;
-        objects[3] = mSinceCreationMillis;
-        objects[4] = mSinceUpdateMillis;
-        objects[5] = mSinceVisibleMillis;
-
-        LogMaker proto = validateGoodData(t, "", objects);
-        validateNotificationTimes(proto, mSinceCreationMillis, mSinceUpdateMillis,
-                mSinceVisibleMillis);
-    }
-
-    public void testIgnoreUnexpectedData() throws Throwable {
-        int t = 1000;
-        int byUser = 1;
-        int expanded = 1;
-        Object[] objects = new Object[7];
-        objects[0] = mKey;
-        objects[1] = byUser;
-        objects[2] = expanded;
-        objects[3] = mSinceCreationMillis;
-        objects[4] = mSinceUpdateMillis;
-        objects[5] = mSinceVisibleMillis;
-        objects[6] = "foo";
-
-        validateGoodData(t, "", objects);
-    }
-}
diff --git a/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationKeyTest.java b/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationKeyTest.java
deleted file mode 100644
index b509700..0000000
--- a/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationKeyTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import android.test.InstrumentationTestCase;
-
-public class NotificationKeyTest extends InstrumentationTestCase {
-
-    private final NotificationKey mKey;
-
-    public NotificationKeyTest() {
-        mKey = new NotificationKey();
-    }
-
-    public void testGoodKey() throws Throwable {
-        assertTrue(mKey.parse("1|com.android.example.notificationshowcase|31338|null|10090"));
-
-        assertEquals("com.android.example.notificationshowcase", mKey.mPackageName);
-        assertEquals("", mKey.mTag);
-        assertEquals(31338, mKey.mId);
-        assertEquals(1, mKey.mUser);
-        assertEquals(10090, mKey.mUid);
-    }
-
-    public void testTaggedKey() throws Throwable {
-        assertTrue(mKey.parse("1|com.android.example.notificationshowcase|31338|foo|10090"));
-
-        assertEquals("com.android.example.notificationshowcase", mKey.mPackageName);
-        assertEquals("foo", mKey.mTag);
-        assertEquals(31338, mKey.mId);
-        assertEquals(1, mKey.mUser);
-        assertEquals(10090, mKey.mUid);
-    }
-
-    public void testEmptyTag() throws Throwable {
-        assertTrue(mKey.parse("1|com.android.example.notificationshowcase|31338||10090"));
-
-        assertEquals("com.android.example.notificationshowcase", mKey.mPackageName);
-        assertEquals("", mKey.mTag);
-        assertEquals(31338, mKey.mId);
-        assertEquals(1, mKey.mUser);
-        assertEquals(10090, mKey.mUid);
-    }
-
-    public void testBadKeys() throws Throwable {
-        assertFalse(mKey.parse(null));
-        assertFalse(mKey.parse(""));
-        assertFalse(mKey.parse("foo"));  // not a key
-        assertFalse(mKey.parse("1|com.android.example.notificationshowcase|31338|null"));
-        assertFalse(mKey.parse("bar|com.android.example.notificationshowcase|31338|null|10090"));
-    }
-}
diff --git a/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationPanelHiddenParserTest.java b/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationPanelHiddenParserTest.java
deleted file mode 100644
index ce6f1f4..0000000
--- a/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationPanelHiddenParserTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-public class NotificationPanelHiddenParserTest extends ParserTest {
-
-    public NotificationPanelHiddenParserTest() {
-        mParser = new NotificationPanelHiddenParser();
-    }
-
-    public void testNoInput() throws Throwable {
-        int t = 1000;
-        Object[] objects = new Object[0];
-
-        validateGoodData(t, objects);
-
-    }
-
-    public void testIgnoreExtraneousInput() throws Throwable {
-        Object[] objects = new Object[1];
-        objects[0] = "nothing to see here";
-
-        validateGoodData(0, objects);
-    }
-
-    private void validateGoodData(int t, Object[] objects) {
-        mParser.parseEvent(mLogger, t, objects);
-
-        verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
-
-        LogMaker proto = mProtoCaptor.getValue();
-        assertEquals(t, proto.getTimestamp());
-        assertEquals(MetricsEvent.NOTIFICATION_PANEL, proto.getCategory());
-        assertEquals(MetricsEvent.TYPE_CLOSE, proto.getType());
-    }
-}
diff --git a/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationPanelRevealedParserTest.java b/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationPanelRevealedParserTest.java
deleted file mode 100644
index 9e15812..0000000
--- a/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationPanelRevealedParserTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import static org.mockito.Matchers.anyObject;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-public class NotificationPanelRevealedParserTest extends ParserTest {
-
-    public NotificationPanelRevealedParserTest() {
-        mParser = new NotificationPanelRevealedParser();
-    }
-
-    public void testLollipopInput() throws Throwable {
-        int t = 1000;
-        Object[] objects = new Object[0];
-
-        mParser.parseEvent(mLogger, t, objects);
-
-        verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
-
-        LogMaker proto = mProtoCaptor.getValue();
-        assertEquals(t, proto.getTimestamp());
-        assertEquals(MetricsEvent.NOTIFICATION_PANEL, proto.getCategory());
-        assertEquals(MetricsEvent.TYPE_OPEN, proto.getType());
-    }
-
-    public void testMncData() throws Throwable {
-        int t = 1000;
-        int n = 5;
-        Object[] objects = new Object[1];
-        objects[0] = Integer.valueOf(n);
-
-        validateMncData(t, n, objects);
-    }
-
-    private void validateMncData(int t, int n, Object[] objects) {
-        mParser.parseEvent(mLogger, t, objects);
-
-        verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
-
-        LogMaker proto = mProtoCaptor.getValue();
-        assertEquals(t, proto.getTimestamp());
-        assertEquals(MetricsEvent.NOTIFICATION_PANEL, proto.getCategory());
-        assertEquals(MetricsEvent.TYPE_OPEN, proto.getType());
-    }
-
-    public void testBadInput() throws Throwable {
-        Object[] objects = new Object[1];
-        objects[0] = "This is not the integer you're looking for.";
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, times(1)).addEvent((LogMaker) anyObject());
-    }
-
-    public void testIgnoreUnexpectedData() throws Throwable {
-        int t = 1000;
-        int n = 5;
-        Object[] objects = new Object[2];
-        objects[0] = Integer.valueOf(n);
-        objects[1] = "foo";
-
-        validateMncData(t, n, objects);
-    }
-}
diff --git a/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationVisibilityParserTest.java b/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationVisibilityParserTest.java
deleted file mode 100644
index 7fef929..0000000
--- a/core/tests/coretests/src/com/android/internal/logging/legacy/NotificationVisibilityParserTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import static junit.framework.Assert.assertTrue;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-public class NotificationVisibilityParserTest extends ParserTest {
-    private final int mCreationTime = 23124;
-    private final int mUpdateTime = 3412;
-    private final int mTime = 1000;
-
-    public NotificationVisibilityParserTest() {
-        mParser = new NotificationVisibilityParser();
-    }
-
-    public void testReveal() throws Throwable {
-        Object[] objects = new Object[4];
-        objects[0] = mTaggedKey;
-        objects[1] = 1;
-        objects[2] = mCreationTime;
-        objects[3] = mUpdateTime;
-
-        validateInteraction(true, mUpdateTime, 0, objects);
-    }
-
-    public void testHide() throws Throwable {
-        Object[] objects = new Object[4];
-        objects[0] = mTaggedKey;
-        objects[1] = 0;
-        objects[2] = mCreationTime;
-        objects[3] = mUpdateTime;
-
-        validateInteraction(false, mUpdateTime, 0, objects);
-    }
-
-    public void testIgnoreUnexpectedData() throws Throwable {
-        Object[] objects = new Object[5];
-        objects[0] = mTaggedKey;
-        objects[1] = 1;
-        objects[2] = mCreationTime;
-        objects[3] = mUpdateTime;
-        objects[4] = "foo";
-
-        validateInteraction(true, mUpdateTime, 0, objects);
-    }
-
-    public void testMarshmallowIndexData() throws Throwable {
-        Object[] objects = new Object[6];
-        objects[0] = mTaggedKey;
-        objects[1] = 1;
-        objects[2] = mCreationTime;
-        objects[3] = mUpdateTime;
-        objects[4] = 0;
-        objects[5] = 3;
-
-        validateInteraction(true, mUpdateTime, 3, objects);
-    }
-
-    private void validateInteraction(boolean visible, int freshness, int index, Object[] objects)    {
-        mParser.parseEvent(mLogger, mTime, objects);
-
-        verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
-
-        LogMaker proto = mProtoCaptor.getValue();
-        assertEquals(mTime, proto.getTimestamp());
-        assertEquals(MetricsEvent.NOTIFICATION_ITEM, proto.getCategory());
-        assertEquals(mKeyPackage, proto.getPackageName());
-        validateNotificationIdAndTag(proto, mId, mTag);
-        validateNotificationTimes(proto, mCreationTime, mUpdateTime);
-        assertEquals(index, proto.getTaggedData(MetricsEvent.NOTIFICATION_SHADE_INDEX));
-        assertEquals(visible ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE, proto.getType());
-    }
-}
diff --git a/core/tests/coretests/src/com/android/internal/logging/legacy/SysuiActionParserTest.java b/core/tests/coretests/src/com/android/internal/logging/legacy/SysuiActionParserTest.java
deleted file mode 100644
index 2ad76c1..0000000
--- a/core/tests/coretests/src/com/android/internal/logging/legacy/SysuiActionParserTest.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyObject;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-public class SysuiActionParserTest extends ParserTest {
-
-    public SysuiActionParserTest() {
-        mParser = new SysuiActionParser();
-    }
-
-    public void testGoodDatal() throws Throwable {
-        int t = 1000;
-        int view = 10;
-        Object[] objects = new Object[1];
-        objects[0] = view;
-
-        validateGoodData(t, view, objects);
-    }
-
-    private void validateGoodData(int t, int view, Object[] objects) {
-        mParser.parseEvent(mLogger, t, objects);
-
-        verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
-        verify(mLogger, never()).incrementBy(anyString(), anyInt());
-
-        LogMaker proto = mProtoCaptor.getValue();
-        assertEquals(t, proto.getTimestamp());
-        assertEquals(view, proto.getCategory());
-        assertEquals(MetricsEvent.TYPE_ACTION, proto.getType());
-    }
-
-    public void testGoodDataWithPackage() throws Throwable {
-        int t = 1000;
-        int view = 10;
-        String packageName = "com.foo";
-        Object[] objects = new Object[2];
-        objects[0] = view;
-        objects[1] = packageName;
-
-        mParser.parseEvent(mLogger, t, objects);
-
-        verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
-        verify(mLogger, never()).incrementBy(anyString(), anyInt());
-
-        LogMaker proto = mProtoCaptor.getValue();
-        assertEquals(t, proto.getTimestamp());
-        assertEquals(view, proto.getCategory());
-        assertEquals(packageName, proto.getPackageName());
-        assertEquals(MetricsEvent.TYPE_ACTION, proto.getType());
-    }
-
-    public void testGoodDataWithTrue() throws Throwable {
-        validateSubType(Boolean.toString(true), 1);
-    }
-
-    public void testGoodDataWithFalse() throws Throwable {
-        validateSubType(Boolean.toString(false), 0);
-    }
-
-    public void testGoodDataWithIntZero() throws Throwable {
-        validateSubType(Integer.toString(0), 0);
-    }
-
-    public void testGoodDataWithIntONe() throws Throwable {
-        validateSubType(Integer.toString(1), 1);
-    }
-
-    public void testGoodDataWithIntTwo() throws Throwable {
-        validateSubType(Integer.toString(2), 2);
-    }
-
-    public void testGoodDataWithNegativeInt() throws Throwable {
-        validateSubType(Integer.toString(-1), -1);
-    }
-
-    public void testGoodDataWithIntLarge() throws Throwable {
-        validateSubType(Integer.toString(120312), 120312);
-    }
-
-    public void testGoodDataWithNegativeIntLarge() throws Throwable {
-        validateSubType(Integer.toString(-120312), -120312);
-    }
-
-    private void validateSubType(String arg, int expectedValue) {
-        int t = 1000;
-        int view = 10;
-        Object[] objects = new Object[2];
-        objects[0] = view;
-        objects[1] = arg;
-
-        mParser.parseEvent(mLogger, t, objects);
-
-        verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
-        verify(mLogger, never()).incrementBy(anyString(), anyInt());
-
-        LogMaker proto = mProtoCaptor.getValue();
-        assertEquals(t, proto.getTimestamp());
-        assertEquals(view, proto.getCategory());
-        assertEquals(expectedValue, proto.getSubtype());
-        assertNull(proto.getPackageName());
-        assertEquals(MetricsEvent.TYPE_ACTION, proto.getType());
-    }
-
-    public void testIgnoreMissingInput() throws Throwable {
-        Object[] objects = new Object[0];
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-        verify(mLogger, never()).incrementBy(anyString(), anyInt());
-    }
-
-    public void testIgnoreWrongInputs() throws Throwable {
-        Object[] objects = new Object[2];
-        objects[0] = "nothing to see here";
-        objects[1] = 10;
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-        verify(mLogger, never()).incrementBy(anyString(), anyInt());
-    }
-
-    public void testIgnoreStringViewInput() throws Throwable {
-        Object[] objects = new Object[1];
-        objects[0] = "this is not the input you are looking for";
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-        verify(mLogger, never()).incrementBy(anyString(), anyInt());
-    }
-
-    public void testIgnoreUnexpectedData() throws Throwable {
-        int t = 1000;
-        int view = 10;
-        Object[] objects = new Object[2];
-        objects[0] = view;
-        objects[1] = "foo";
-
-        validateGoodData(t, view, objects);
-    }
-}
diff --git a/core/tests/coretests/src/com/android/internal/logging/legacy/SysuiViewVisibilityParserTest.java b/core/tests/coretests/src/com/android/internal/logging/legacy/SysuiViewVisibilityParserTest.java
deleted file mode 100644
index 64d69a4..0000000
--- a/core/tests/coretests/src/com/android/internal/logging/legacy/SysuiViewVisibilityParserTest.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.logging.legacy;
-
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyObject;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-
-import android.metrics.LogMaker;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
-public class SysuiViewVisibilityParserTest extends ParserTest {
-
-    public SysuiViewVisibilityParserTest() {
-        mParser = new SysuiViewVisibilityParser();
-    }
-
-    public void testViewReveal() throws Throwable {
-        int t = 1000;
-        int view = 10;
-        Object[] objects = new Object[2];
-        objects[0] = view;
-        objects[1] = 100;
-
-        validateViewReveal(t, view, objects);
-    }
-
-    private void validateViewReveal(int t, int view, Object[] objects) {
-        mParser.parseEvent(mLogger, t, objects);
-
-        verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
-
-        LogMaker proto = mProtoCaptor.getValue();
-        assertEquals(t, proto.getTimestamp());
-        assertEquals(view, proto.getCategory());
-        assertEquals(MetricsEvent.TYPE_OPEN, proto.getType());
-    }
-
-    public void testViewHidden() throws Throwable {
-        int t = 1000;
-        int view = 10;
-        Object[] objects = new Object[2];
-        objects[0] = view;
-        objects[1] = 0;
-
-        mParser.parseEvent(mLogger, t, objects);
-
-        verify(mLogger, times(1)).addEvent(mProtoCaptor.capture());
-
-        LogMaker proto = mProtoCaptor.getValue();
-        assertEquals(MetricsEvent.TYPE_CLOSE, proto.getType());
-    }
-
-    public void testIgnoreMissingInput() throws Throwable {
-        Object[] objects = new Object[0];
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-        verify(mLogger, never()).incrementBy(anyString(), anyInt());
-    }
-
-    public void testIgnoreStringInARgOne() throws Throwable {
-        Object[] objects = new Object[2];
-        objects[0] = "nothing to see here";
-        objects[1] = 100;
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-        verify(mLogger, never()).incrementBy(anyString(), anyInt());
-    }
-
-    public void testIgnoreStringInArgTwo() throws Throwable {
-        Object[] objects = new Object[2];
-        objects[0] = 100;
-        objects[1] = "nothing to see here";
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-        verify(mLogger, never()).incrementBy(anyString(), anyInt());
-    }
-
-    public void testOneInput() throws Throwable {
-        Object[] objects = new Object[1];
-        objects[0] = 100;
-
-        mParser.parseEvent(mLogger, 0, objects);
-
-        verify(mLogger, never()).addEvent((LogMaker) anyObject());
-        verify(mLogger, never()).incrementBy(anyString(), anyInt());
-    }
-
-    public void testIgnoreUnexpectedData() throws Throwable {
-        int t = 1000;
-        int view = 10;
-        Object[] objects = new Object[3];
-        objects[0] = view;
-        objects[1] = 100;
-        objects[2] = "foo";
-
-        validateViewReveal(t, view, objects);
-    }
-}
diff --git a/docs/html/about/versions/android-4.0.jd b/docs/html/about/versions/android-4.0.jd
index 48afcd4..421019c 100644
--- a/docs/html/about/versions/android-4.0.jd
+++ b/docs/html/about/versions/android-4.0.jd
@@ -309,7 +309,7 @@
 android.media.effect.EffectContext#getFactory EffectContext.getFactory()}, which returns an instance
 of {@link android.media.effect.EffectFactory}.</li>
 <li>Call {@link android.media.effect.EffectFactory#createEffect createEffect()}, passing it an
-effect name from @link android.media.effect.EffectFactory}, such as {@link
+effect name from {@link android.media.effect.EffectFactory}, such as {@link
 android.media.effect.EffectFactory#EFFECT_FISHEYE} or {@link
 android.media.effect.EffectFactory#EFFECT_VIGNETTE}.</li>
 </ol>
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index 3e59f34..1c85df0 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -119,7 +119,7 @@
      * Currently, only Outlines that can be represented as a rectangle, circle,
      * or round rect support clipping.
      *
-     * @see {@link android.view.View#setClipToOutline(boolean)}
+     * @see android.view.View#setClipToOutline(boolean)
      */
     public boolean canClip() {
         return mMode != MODE_CONVEX_PATH;
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 38e8061..2e6a901 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.res.AssetManager;
 import android.graphics.fonts.FontRequest;
 import android.graphics.fonts.FontResult;
@@ -131,9 +132,9 @@
 
     /**
      * @hide
-     * Used by Resources.
+     * Used by Resources to load a font resource of type font file.
      */
-    @NonNull
+    @Nullable
     public static Typeface createFromResources(AssetManager mgr, String path, int cookie) {
         if (sFallbackFonts != null) {
             synchronized (sDynamicTypefaceCache) {
@@ -143,6 +144,7 @@
 
                 FontFamily fontFamily = new FontFamily();
                 if (fontFamily.addFontFromAssetManager(mgr, path, cookie, false /* isAsset */)) {
+                    fontFamily.freeze();
                     FontFamily[] families = {fontFamily};
                     typeface = createFromFamiliesWithDefault(families);
                     sDynamicTypefaceCache.put(key, typeface);
@@ -150,7 +152,62 @@
                 }
             }
         }
-        throw new RuntimeException("Font resource not found " + path);
+        return null;
+    }
+
+    /**
+     * @hide
+     * Used by Resources to load a font resource of type xml.
+     */
+    @Nullable
+    public static Typeface createFromResources(FontConfig config, AssetManager mgr, String path) {
+        if (sFallbackFonts != null) {
+            synchronized (sDynamicTypefaceCache) {
+                final String key = createAssetUid(mgr, path);
+                Typeface typeface = sDynamicTypefaceCache.get(key);
+                if (typeface != null) return typeface;
+
+                List<FontConfig.Family> families = config.getFamilies();
+                if (families == null || families.isEmpty()) {
+                    throw new RuntimeException("Font resource contained no fonts.");
+                }
+                if (families.size() > 1) {
+                    throw new RuntimeException("Font resource contained more than one family.");
+                }
+                FontConfig.Family family = families.get(0);
+
+                FontFamily fontFamily = new FontFamily();
+                List<FontConfig.Font> fonts = family.getFonts();
+                for (int i = 0; i < fonts.size(); i++) {
+                    FontConfig.Font font = fonts.get(i);
+                    // TODO: Use style and weight info
+                    if (!fontFamily.addFontFromAssetManager(mgr, font.getFontName(),
+                            0 /* resourceCookie */, false /* isAsset */)) {
+                        return null;
+                    }
+                }
+                fontFamily.freeze();
+                FontFamily[] familyChain = { fontFamily };
+                typeface = createFromFamiliesWithDefault(familyChain);
+                sDynamicTypefaceCache.put(key, typeface);
+                return typeface;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * @hide
+     */
+    public static Typeface createFromCache(AssetManager mgr, String path) {
+        synchronized (sDynamicTypefaceCache) {
+            final String key = createAssetUid(mgr, path);
+            Typeface typeface = sDynamicTypefaceCache.get(key);
+            if (typeface != null) {
+                return typeface;
+            }
+        }
+        return null;
     }
 
     /**
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 6ddc2d7..850f40e 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -1320,7 +1320,7 @@
          * provide an appropriate Resources object.
          *
          * @return a new drawable object based on this constant state
-         * @see {@link #newDrawable(Resources)}
+         * @see #newDrawable(Resources)
          */
         public abstract @NonNull Drawable newDrawable();
 
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index fb89835..ecf6bd4 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -38,6 +38,7 @@
         "ResourceTypes.cpp",
         "StreamingZipInflater.cpp",
         "TypeWrappers.cpp",
+        "Util.cpp",
         "ZipFileRO.cpp",
         "ZipUtils.cpp",
     ],
@@ -82,6 +83,9 @@
         },
         windows: {
             enabled: true,
+            cppflags: ["-Wno-missing-field-initializers"],  // The Windows compiler warns
+                                                            // incorrectly for value
+                                                            // initialization with {}.
         },
     },
 }
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index 55f4c3c..9a08f63 100644
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -28,7 +28,16 @@
 namespace android {
 
 std::unique_ptr<ApkAssets> ApkAssets::Load(const std::string& path) {
-  ATRACE_NAME("ApkAssets::Load");
+  return ApkAssets::LoadImpl(path, false /*load_as_shared_library*/);
+}
+
+std::unique_ptr<ApkAssets> ApkAssets::LoadAsSharedLibrary(const std::string& path) {
+  return ApkAssets::LoadImpl(path, true /*load_as_shared_library*/);
+}
+
+std::unique_ptr<ApkAssets> ApkAssets::LoadImpl(const std::string& path,
+                                               bool load_as_shared_library) {
+  ATRACE_CALL();
   ::ZipArchiveHandle unmanaged_handle;
   int32_t result = ::OpenArchive(path.c_str(), &unmanaged_handle);
   if (result != 0) {
@@ -61,7 +70,7 @@
   loaded_apk->path_ = path;
   loaded_apk->loaded_arsc_ =
       LoadedArsc::Load(loaded_apk->resources_asset_->getBuffer(true /*wordAligned*/),
-                       loaded_apk->resources_asset_->getLength());
+                       loaded_apk->resources_asset_->getLength(), load_as_shared_library);
   if (loaded_apk->loaded_arsc_ == nullptr) {
     return {};
   }
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 8d65925..d2eff65 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -36,13 +36,84 @@
 bool AssetManager2::SetApkAssets(const std::vector<const ApkAssets*>& apk_assets,
                                  bool invalidate_caches) {
   apk_assets_ = apk_assets;
+  BuildDynamicRefTable();
   if (invalidate_caches) {
     InvalidateCaches(static_cast<uint32_t>(-1));
   }
   return true;
 }
 
-const std::vector<const ApkAssets*> AssetManager2::GetApkAssets() const { return apk_assets_; }
+void AssetManager2::BuildDynamicRefTable() {
+  package_groups_.clear();
+  package_ids_.fill(0xff);
+
+  // 0x01 is reserved for the android package.
+  int next_package_id = 0x02;
+  const size_t apk_assets_count = apk_assets_.size();
+  for (size_t i = 0; i < apk_assets_count; i++) {
+    const ApkAssets* apk_asset = apk_assets_[i];
+    for (const std::unique_ptr<const LoadedPackage>& package :
+         apk_asset->GetLoadedArsc()->GetPackages()) {
+      // Get the package ID or assign one if a shared library.
+      int package_id;
+      if (package->IsDynamic()) {
+        package_id = next_package_id++;
+      } else {
+        package_id = package->GetPackageId();
+      }
+
+      // Add the mapping for package ID to index if not present.
+      uint8_t idx = package_ids_[package_id];
+      if (idx == 0xff) {
+        package_ids_[package_id] = idx = static_cast<uint8_t>(package_groups_.size());
+        package_groups_.push_back({});
+        package_groups_.back().dynamic_ref_table.mAssignedPackageId = package_id;
+      }
+      PackageGroup* package_group = &package_groups_[idx];
+
+      // Add the package and to the set of packages with the same ID.
+      package_group->packages_.push_back(package.get());
+      package_group->cookies_.push_back(static_cast<ApkAssetsCookie>(i));
+
+      // Add the package name -> build time ID mappings.
+      for (const DynamicPackageEntry& entry : package->GetDynamicPackageMap()) {
+        String16 package_name(entry.package_name.c_str(), entry.package_name.size());
+        package_group->dynamic_ref_table.mEntries.replaceValueFor(
+            package_name, static_cast<uint8_t>(entry.package_id));
+      }
+    }
+  }
+
+  // Now assign the runtime IDs so that we have a build-time to runtime ID map.
+  const auto package_groups_end = package_groups_.end();
+  for (auto iter = package_groups_.begin(); iter != package_groups_end; ++iter) {
+    const std::string& package_name = iter->packages_[0]->GetPackageName();
+    for (auto iter2 = package_groups_.begin(); iter2 != package_groups_end; ++iter2) {
+      iter2->dynamic_ref_table.addMapping(String16(package_name.c_str(), package_name.size()),
+                                          iter->dynamic_ref_table.mAssignedPackageId);
+    }
+  }
+}
+
+void AssetManager2::DumpToLog() const {
+  base::ScopedLogSeverity _log(base::INFO);
+
+  std::string list;
+  for (size_t i = 0; i < package_ids_.size(); i++) {
+    if (package_ids_[i] != 0xff) {
+      base::StringAppendF(&list, "%02x -> %d, ", (int) i, package_ids_[i]);
+    }
+  }
+  LOG(INFO) << "Package ID map: " << list;
+
+  for (const auto& package_group: package_groups_) {
+      list = "";
+      for (const auto& package : package_group.packages_) {
+        base::StringAppendF(&list, "%s(%02x), ", package->GetPackageName().c_str(), package->GetPackageId());
+      }
+      LOG(INFO) << base::StringPrintf("PG (%02x): ", package_group.dynamic_ref_table.mAssignedPackageId) << list;
+  }
+}
 
 const ResStringPool* AssetManager2::GetStringPoolForCookie(ApkAssetsCookie cookie) const {
   if (cookie < 0 || static_cast<size_t>(cookie) >= apk_assets_.size()) {
@@ -51,6 +122,18 @@
   return apk_assets_[cookie]->GetLoadedArsc()->GetStringPool();
 }
 
+const DynamicRefTable* AssetManager2::GetDynamicRefTableForPackage(uint32_t package_id) const {
+  if (package_id >= package_ids_.size()) {
+    return nullptr;
+  }
+
+  const size_t idx = package_ids_[package_id];
+  if (idx == 0xff) {
+    return nullptr;
+  }
+  return &package_groups_[idx].dynamic_ref_table;
+}
+
 void AssetManager2::SetConfiguration(const ResTable_config& configuration) {
   const int diff = configuration_.diff(configuration);
   configuration_ = configuration;
@@ -60,8 +143,6 @@
   }
 }
 
-const ResTable_config& AssetManager2::GetConfiguration() const { return configuration_; }
-
 std::unique_ptr<Asset> AssetManager2::Open(const std::string& filename, Asset::AccessMode mode) {
   const std::string new_path = "assets/" + filename;
   return OpenNonAsset(new_path, mode);
@@ -106,7 +187,7 @@
 }
 
 ApkAssetsCookie AssetManager2::FindEntry(uint32_t resid, uint16_t density_override,
-                                         bool stop_at_first_match, LoadedArsc::Entry* out_entry,
+                                         bool stop_at_first_match, LoadedArscEntry* out_entry,
                                          ResTable_config* out_selected_config,
                                          uint32_t* out_flags) {
   ATRACE_CALL();
@@ -122,48 +203,66 @@
     desired_config = &density_override_config;
   }
 
-  LoadedArsc::Entry best_entry;
+  const uint32_t package_id = util::get_package_id(resid);
+  const uint8_t type_id = util::get_type_id(resid);
+  const uint16_t entry_id = util::get_entry_id(resid);
+
+  if (type_id == 0) {
+    LOG(ERROR) << base::StringPrintf("Invalid ID 0x%08x.", resid);
+    return kInvalidCookie;
+  }
+
+  const uint8_t idx = package_ids_[package_id];
+  if (idx == 0xff) {
+    LOG(ERROR) << base::StringPrintf("No package ID %02x found for ID 0x%08x.", package_id, resid);
+    return kInvalidCookie;
+  }
+
+  LoadedArscEntry best_entry;
   ResTable_config best_config;
-  int32_t best_index = -1;
-  uint32_t cumulated_flags = 0;
+  ApkAssetsCookie best_cookie = kInvalidCookie;
+  uint32_t cumulated_flags = 0u;
 
-  const size_t apk_asset_count = apk_assets_.size();
-  for (size_t i = 0; i < apk_asset_count; i++) {
-    const LoadedArsc* loaded_arsc = apk_assets_[i]->GetLoadedArsc();
-
-    LoadedArsc::Entry current_entry;
+  const PackageGroup& package_group = package_groups_[idx];
+  const size_t package_count = package_group.packages_.size();
+  for (size_t i = 0; i < package_count; i++) {
+    LoadedArscEntry current_entry;
     ResTable_config current_config;
-    uint32_t flags = 0;
-    if (!loaded_arsc->FindEntry(resid, *desired_config, &current_entry, &current_config, &flags)) {
+    uint32_t current_flags = 0;
+
+    const LoadedPackage* loaded_package = package_group.packages_[i];
+    if (!loaded_package->FindEntry(type_id - 1, entry_id, *desired_config, &current_entry,
+                                   &current_config, &current_flags)) {
       continue;
     }
 
-    cumulated_flags |= flags;
+    cumulated_flags |= current_flags;
 
-    if (best_index == -1 || current_config.isBetterThan(best_config, desired_config)) {
+    if (best_cookie == kInvalidCookie || current_config.isBetterThan(best_config, desired_config)) {
       best_entry = current_entry;
       best_config = current_config;
-      best_index = static_cast<int32_t>(i);
+      best_cookie = package_group.cookies_[i];
       if (stop_at_first_match) {
         break;
       }
     }
   }
 
-  if (best_index == -1) {
+  if (best_cookie == kInvalidCookie) {
     return kInvalidCookie;
   }
 
   *out_entry = best_entry;
+  out_entry->dynamic_ref_table = &package_group.dynamic_ref_table;
   *out_selected_config = best_config;
   *out_flags = cumulated_flags;
-  return best_index;
+  return best_cookie;
 }
 
 bool AssetManager2::GetResourceName(uint32_t resid, ResourceName* out_name) {
   ATRACE_CALL();
 
-  LoadedArsc::Entry entry;
+  LoadedArscEntry entry;
   ResTable_config config;
   uint32_t flags = 0u;
   ApkAssetsCookie cookie = FindEntry(resid, 0u /* density_override */,
@@ -172,14 +271,13 @@
     return false;
   }
 
-  const std::string* package_name =
-      apk_assets_[cookie]->GetLoadedArsc()->GetPackageNameForId(resid);
-  if (package_name == nullptr) {
+  const LoadedPackage* package = apk_assets_[cookie]->GetLoadedArsc()->GetPackageForId(resid);
+  if (package == nullptr) {
     return false;
   }
 
-  out_name->package = package_name->data();
-  out_name->package_len = package_name->size();
+  out_name->package = package->GetPackageName().data();
+  out_name->package_len = package->GetPackageName().size();
 
   out_name->type = entry.type_string_ref.string8(&out_name->type_len);
   out_name->type16 = nullptr;
@@ -202,7 +300,7 @@
 }
 
 bool AssetManager2::GetResourceFlags(uint32_t resid, uint32_t* out_flags) {
-  LoadedArsc::Entry entry;
+  LoadedArscEntry entry;
   ResTable_config config;
   ApkAssetsCookie cookie = FindEntry(resid, 0u /* density_override */,
                                      false /* stop_at_first_match */, &entry, &config, out_flags);
@@ -215,7 +313,7 @@
                                            uint32_t* out_flags) {
   ATRACE_CALL();
 
-  LoadedArsc::Entry entry;
+  LoadedArscEntry entry;
   ResTable_config config;
   uint32_t flags = 0u;
   ApkAssetsCookie cookie =
@@ -234,6 +332,10 @@
   const Res_value* device_value = reinterpret_cast<const Res_value*>(
       reinterpret_cast<const uint8_t*>(entry.entry) + dtohs(entry.entry->size));
   out_value->copyFrom_dtoh(*device_value);
+
+  // Convert the package ID to the runtime assigned package ID.
+  entry.dynamic_ref_table->lookupResourceValue(out_value);
+
   *out_selected_config = config;
   *out_flags = flags;
   return cookie;
@@ -247,7 +349,7 @@
     return cached_iter->second.get();
   }
 
-  LoadedArsc::Entry entry;
+  LoadedArscEntry entry;
   ResTable_config config;
   uint32_t flags = 0u;
   ApkAssetsCookie cookie = FindEntry(resid, 0u /* density_override */,
@@ -270,8 +372,8 @@
       reinterpret_cast<const ResTable_map*>(reinterpret_cast<const uint8_t*>(map) + map->size);
   const ResTable_map* const map_entry_end = map_entry + dtohl(map->count);
 
-  const uint32_t parent = dtohl(map->parent.ident);
-  if (parent == 0) {
+  uint32_t parent_resid = dtohl(map->parent.ident);
+  if (parent_resid == 0) {
     // There is no parent, meaning there is nothing to inherit and we can do a simple
     // copy of the entries in the map.
     const size_t entry_count = map_entry_end - map_entry;
@@ -279,9 +381,18 @@
         malloc(sizeof(ResolvedBag) + (entry_count * sizeof(ResolvedBag::Entry))))};
     ResolvedBag::Entry* new_entry = new_bag->entries;
     for (; map_entry != map_entry_end; ++map_entry) {
+      uint32_t new_key = dtohl(map_entry->name.ident);
+      if (!util::is_internal_resid(new_key)) {
+        // Attributes, arrays, etc don't have a resource id as the name. They specify
+        // other data, which would be wrong to change via a lookup.
+        if (entry.dynamic_ref_table->lookupResourceId(&new_key) != NO_ERROR) {
+          LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", new_key, resid);
+          return nullptr;
+        }
+      }
       new_entry->cookie = cookie;
       new_entry->value.copyFrom_dtoh(map_entry->value);
-      new_entry->key = dtohl(map_entry->name.ident);
+      new_entry->key = new_key;
       new_entry->key_pool = nullptr;
       new_entry->type_pool = nullptr;
       ++new_entry;
@@ -293,10 +404,14 @@
     return result;
   }
 
+  // In case the parent is a dynamic reference, resolve it.
+  entry.dynamic_ref_table->lookupResourceId(&parent_resid);
+
   // Get the parent and do a merge of the keys.
-  const ResolvedBag* parent_bag = GetBag(parent);
+  const ResolvedBag* parent_bag = GetBag(parent_resid);
   if (parent_bag == nullptr) {
     // Failed to get the parent that should exist.
+    LOG(ERROR) << base::StringPrintf("Failed to find parent 0x%08x of bag 0x%08x.", parent_resid, resid);
     return nullptr;
   }
 
@@ -315,7 +430,14 @@
 
   // The keys are expected to be in sorted order. Merge the two bags.
   while (map_entry != map_entry_end && parent_entry != parent_entry_end) {
-    const uint32_t child_key = dtohl(map_entry->name.ident);
+    uint32_t child_key = dtohl(map_entry->name.ident);
+    if (!util::is_internal_resid(child_key)) {
+      if (entry.dynamic_ref_table->lookupResourceId(&child_key) != NO_ERROR) {
+        LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", child_key, resid);
+        return nullptr;
+      }
+    }
+
     if (child_key <= parent_entry->key) {
       // Use the child key if it comes before the parent
       // or is equal to the parent (overrides).
@@ -340,9 +462,16 @@
 
   // Finish the child entries if they exist.
   while (map_entry != map_entry_end) {
+    uint32_t new_key = dtohl(map_entry->name.ident);
+    if (!util::is_internal_resid(new_key)) {
+      if (entry.dynamic_ref_table->lookupResourceId(&new_key) != NO_ERROR) {
+        LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", new_key, resid);
+        return nullptr;
+      }
+    }
     new_entry->cookie = cookie;
     new_entry->value.copyFrom_dtoh(map_entry->value);
-    new_entry->key = dtohl(map_entry->name.ident);
+    new_entry->key = new_key;
     new_entry->key_pool = nullptr;
     new_entry->type_pool = nullptr;
     ++map_entry;
@@ -511,12 +640,43 @@
     type_spec_flags |= entry.type_spec_flags;
 
     switch (entry.value.dataType) {
+      case Res_value::TYPE_NULL:
+        return kInvalidCookie;
+
       case Res_value::TYPE_ATTRIBUTE:
         resid = entry.value.data;
         break;
 
-      case Res_value::TYPE_NULL:
-        return kInvalidCookie;
+      case Res_value::TYPE_DYNAMIC_ATTRIBUTE: {
+        // Resolve the dynamic attribute to a normal attribute
+        // (with the right package ID).
+        resid = entry.value.data;
+        const DynamicRefTable* ref_table =
+            asset_manager_->GetDynamicRefTableForPackage(package_idx);
+        if (ref_table == nullptr || ref_table->lookupResourceId(&resid) != NO_ERROR) {
+          LOG(ERROR) << base::StringPrintf("Failed to resolve dynamic attribute 0x%08x", resid);
+          return kInvalidCookie;
+        }
+      } break;
+
+      case Res_value::TYPE_DYNAMIC_REFERENCE: {
+        // Resolve the dynamic reference to a normal reference
+        // (with the right package ID).
+        out_value->dataType = Res_value::TYPE_REFERENCE;
+        out_value->data = entry.value.data;
+        const DynamicRefTable* ref_table =
+            asset_manager_->GetDynamicRefTableForPackage(package_idx);
+        if (ref_table == nullptr || ref_table->lookupResourceId(&out_value->data) != NO_ERROR) {
+          LOG(ERROR) << base::StringPrintf("Failed to resolve dynamic reference 0x%08x",
+                                           out_value->data);
+          return kInvalidCookie;
+        }
+
+        if (out_flags != nullptr) {
+          *out_flags = type_spec_flags;
+        }
+        return entry.cookie;
+      }
 
       default:
         *out_value = entry.value;
@@ -550,14 +710,14 @@
 
   type_spec_flags_ = o.type_spec_flags_;
 
-  for (size_t p = 0; p < arraysize(packages_); p++) {
+  for (size_t p = 0; p < packages_.size(); p++) {
     const Package* package = o.packages_[p].get();
     if (package == nullptr) {
       packages_[p].reset();
       continue;
     }
 
-    for (size_t t = 0; t < arraysize(package->types); t++) {
+    for (size_t t = 0; t < package->types.size(); t++) {
       const Type* type = package->types[t].get();
       if (type == nullptr) {
         packages_[p]->types[t].reset();
diff --git a/libs/androidfw/ChunkIterator.cpp b/libs/androidfw/ChunkIterator.cpp
index 747aa4a..d8adbe5 100644
--- a/libs/androidfw/ChunkIterator.cpp
+++ b/libs/androidfw/ChunkIterator.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "Chunk.h"
+#include "androidfw/Chunk.h"
 
 #include "android-base/logging.h"
 
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index 94d0d46..e17a3a6 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -32,15 +32,15 @@
 #endif
 #endif
 
-#include "Chunk.h"
 #include "androidfw/ByteBucketArray.h"
+#include "androidfw/Chunk.h"
 #include "androidfw/Util.h"
 
 using android::base::StringPrintf;
 
 namespace android {
 
-namespace {
+constexpr const static int kAppPackageId = 0x7f;
 
 // Element of a TypeSpec array. See TypeSpec.
 struct Type {
@@ -76,6 +76,8 @@
 // itself.
 using TypeSpecPtr = util::unique_cptr<TypeSpec>;
 
+namespace {
+
 // Builder that helps accumulate Type structs and then create a single
 // contiguous block of memory to store both the TypeSpec struct and
 // the Type structs.
@@ -110,37 +112,18 @@
 
 }  // namespace
 
-class LoadedPackage {
- public:
-  LoadedPackage() = default;
-
-  bool FindEntry(uint8_t type_id, uint16_t entry_id, const ResTable_config& config,
-                 LoadedArsc::Entry* out_entry, ResTable_config* out_selected_config,
-                 uint32_t* out_flags) const;
-
-  ResStringPool type_string_pool_;
-  ResStringPool key_string_pool_;
-  std::string package_name_;
-  int package_id_ = -1;
-
-  ByteBucketArray<TypeSpecPtr> type_specs_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(LoadedPackage);
-};
-
-bool LoadedPackage::FindEntry(uint8_t type_id, uint16_t entry_id, const ResTable_config& config,
-                              LoadedArsc::Entry* out_entry, ResTable_config* out_selected_config,
+bool LoadedPackage::FindEntry(uint8_t type_idx, uint16_t entry_idx, const ResTable_config& config,
+                              LoadedArscEntry* out_entry, ResTable_config* out_selected_config,
                               uint32_t* out_flags) const {
-  ATRACE_NAME("LoadedPackage::FindEntry");
-  const TypeSpecPtr& ptr = type_specs_[type_id];
+  ATRACE_CALL();
+  const TypeSpecPtr& ptr = type_specs_[type_idx];
   if (ptr == nullptr) {
     return false;
   }
 
   // Don't bother checking if the entry ID is larger than
   // the number of entries.
-  if (entry_id >= dtohl(ptr->type_spec->entryCount)) {
+  if (entry_idx >= dtohl(ptr->type_spec->entryCount)) {
     return false;
   }
 
@@ -156,10 +139,10 @@
       // The configuration matches and is better than the previous selection.
       // Find the entry value if it exists for this configuration.
       size_t entry_count = dtohl(type->type->entryCount);
-      if (entry_id < entry_count) {
+      if (entry_idx < entry_count) {
         const uint32_t* entry_offsets = reinterpret_cast<const uint32_t*>(
             reinterpret_cast<const uint8_t*>(type->type) + dtohs(type->type->header.headerSize));
-        const uint32_t offset = dtohl(entry_offsets[entry_id]);
+        const uint32_t offset = dtohl(entry_offsets[entry_idx]);
         if (offset != ResTable_type::NO_ENTRY) {
           // There is an entry for this resource, record it.
           best_config = &type->configuration;
@@ -175,7 +158,7 @@
   }
 
   const uint32_t* flags = reinterpret_cast<const uint32_t*>(ptr->type_spec + 1);
-  *out_flags = dtohl(flags[entry_id]);
+  *out_flags = dtohl(flags[entry_idx]);
   *out_selected_config = *best_config;
 
   const ResTable_entry* best_entry = reinterpret_cast<const ResTable_entry*>(
@@ -191,9 +174,10 @@
 // forward declarations and incomplete types.
 LoadedArsc::~LoadedArsc() {}
 
-bool LoadedArsc::FindEntry(uint32_t resid, const ResTable_config& config, Entry* out_entry,
-                           ResTable_config* out_selected_config, uint32_t* out_flags) const {
-  ATRACE_NAME("LoadedArsc::FindEntry");
+bool LoadedArsc::FindEntry(uint32_t resid, const ResTable_config& config,
+                           LoadedArscEntry* out_entry, ResTable_config* out_selected_config,
+                           uint32_t* out_flags) const {
+  ATRACE_CALL();
   const uint8_t package_id = util::get_package_id(resid);
   const uint8_t type_id = util::get_type_id(resid);
   const uint16_t entry_id = util::get_entry_id(resid);
@@ -212,11 +196,11 @@
   return false;
 }
 
-const std::string* LoadedArsc::GetPackageNameForId(uint32_t resid) const {
+const LoadedPackage* LoadedArsc::GetPackageForId(uint32_t resid) const {
   const uint8_t package_id = util::get_package_id(resid);
   for (const auto& loaded_package : packages_) {
     if (loaded_package->package_id_ == package_id) {
-      return &loaded_package->package_name_;
+      return loaded_package.get();
     }
   }
   return nullptr;
@@ -334,15 +318,24 @@
   return true;
 }
 
-static bool LoadPackage(const Chunk& chunk, LoadedPackage* loaded_package) {
+std::unique_ptr<LoadedPackage> LoadedPackage::Load(const Chunk& chunk) {
   ATRACE_CALL();
+  std::unique_ptr<LoadedPackage> loaded_package{new LoadedPackage()};
+
   const ResTable_package* header = chunk.header<ResTable_package>();
   if (header == nullptr) {
     LOG(ERROR) << "Chunk RES_TABLE_PACKAGE_TYPE is too small.";
-    return false;
+    return {};
   }
 
   loaded_package->package_id_ = dtohl(header->id);
+  if (loaded_package->package_id_ == 0) {
+    // Package ID of 0 means this is a shared library.
+    loaded_package->dynamic_ = true;
+  }
+
+  util::ReadUtf16StringFromDevice(header->name, arraysize(header->name),
+                                  &loaded_package->package_name_);
 
   // A TypeSpec builder. We use this to accumulate the set of Types
   // available for a TypeSpec, and later build a single, contiguous block
@@ -367,7 +360,7 @@
               child_chunk.header<ResStringPool_header>(), child_chunk.size());
           if (err != NO_ERROR) {
             LOG(ERROR) << "Corrupt package type string pool.";
-            return false;
+            return {};
           }
         } else if (pool_address == header_address + dtohl(header->keyStrings)) {
           // This string pool is the key string pool.
@@ -375,7 +368,7 @@
               child_chunk.header<ResStringPool_header>(), child_chunk.size());
           if (err != NO_ERROR) {
             LOG(ERROR) << "Corrupt package key string pool.";
-            return false;
+            return {};
           }
         } else {
           LOG(WARNING) << "Too many string pool chunks found in package.";
@@ -390,7 +383,7 @@
           TypeSpecPtr type_spec_ptr = types_builder->Build();
           if (type_spec_ptr == nullptr) {
             LOG(ERROR) << "Too many type configurations, overflow detected.";
-            return false;
+            return {};
           }
 
           loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr);
@@ -402,12 +395,12 @@
         const ResTable_typeSpec* type_spec = child_chunk.header<ResTable_typeSpec>();
         if (type_spec == nullptr) {
           LOG(ERROR) << "Chunk RES_TABLE_TYPE_SPEC_TYPE is too small.";
-          return false;
+          return {};
         }
 
         if (type_spec->id == 0) {
           LOG(ERROR) << "Chunk RES_TABLE_TYPE_SPEC_TYPE has invalid ID 0.";
-          return false;
+          return {};
         }
 
         // The data portion of this chunk contains entry_count 32bit entries,
@@ -419,12 +412,12 @@
         // space for entries (EEEE) in the resource ID 0xPPTTEEEE.
         if (entry_count > std::numeric_limits<uint16_t>::max()) {
           LOG(ERROR) << "Too many entries in RES_TABLE_TYPE_SPEC_TYPE: " << entry_count << ".";
-          return false;
+          return {};
         }
 
         if (entry_count * sizeof(uint32_t) > chunk.data_size()) {
           LOG(ERROR) << "Chunk too small to hold entries in RES_TABLE_TYPE_SPEC_TYPE.";
-          return false;
+          return {};
         }
 
         last_type_idx = type_spec->id - 1;
@@ -435,28 +428,63 @@
         const ResTable_type* type = child_chunk.header<ResTable_type>();
         if (type == nullptr) {
           LOG(ERROR) << "Chunk RES_TABLE_TYPE_TYPE is too small.";
-          return false;
+          return {};
         }
 
         if (type->id == 0) {
           LOG(ERROR) << "Chunk RES_TABLE_TYPE_TYPE has invalid ID 0.";
-          return false;
+          return {};
         }
 
         // Type chunks must be preceded by their TypeSpec chunks.
         if (!types_builder || type->id - 1 != last_type_idx) {
           LOG(ERROR) << "Found RES_TABLE_TYPE_TYPE chunk without "
                         "RES_TABLE_TYPE_SPEC_TYPE.";
-          return false;
+          return {};
         }
 
         if (!VerifyType(child_chunk)) {
-          return false;
+          return {};
         }
 
         types_builder->AddType(type);
       } break;
 
+      case RES_TABLE_LIBRARY_TYPE: {
+        const ResTable_lib_header* lib = child_chunk.header<ResTable_lib_header>();
+        if (lib == nullptr) {
+          LOG(ERROR) << "Chunk RES_TABLE_LIBRARY_TYPE is too small.";
+          return {};
+        }
+
+        if (child_chunk.data_size() / sizeof(ResTable_lib_entry) < dtohl(lib->count)) {
+          LOG(ERROR) << "Chunk too small to hold entries in RES_TABLE_LIBRARY_TYPE.";
+          return {};
+        }
+
+        loaded_package->dynamic_package_map_.reserve(dtohl(lib->count));
+
+        const ResTable_lib_entry* const entry_begin =
+            reinterpret_cast<const ResTable_lib_entry*>(child_chunk.data_ptr());
+        const ResTable_lib_entry* const entry_end = entry_begin + dtohl(lib->count);
+        for (auto entry_iter = entry_begin; entry_iter != entry_end; ++entry_iter) {
+          std::string package_name;
+          util::ReadUtf16StringFromDevice(entry_iter->packageName,
+                                          arraysize(entry_iter->packageName), &package_name);
+
+          if (dtohl(entry_iter->packageId) >= std::numeric_limits<uint8_t>::max()) {
+            LOG(ERROR) << base::StringPrintf(
+                "Package ID %02x in RES_TABLE_LIBRARY_TYPE too large for package '%s'.",
+                dtohl(entry_iter->packageId), package_name.c_str());
+            return {};
+          }
+
+          loaded_package->dynamic_package_map_.emplace_back(std::move(package_name),
+                                                            dtohl(entry_iter->packageId));
+        }
+
+      } break;
+
       default:
         LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type());
         break;
@@ -468,19 +496,19 @@
     TypeSpecPtr type_spec_ptr = types_builder->Build();
     if (type_spec_ptr == nullptr) {
       LOG(ERROR) << "Too many type configurations, overflow detected.";
-      return false;
+      return {};
     }
     loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr);
   }
 
   if (iter.HadError()) {
     LOG(ERROR) << iter.GetLastError();
-    return false;
+    return {};
   }
-  return true;
+  return loaded_package;
 }
 
-bool LoadedArsc::LoadTable(const Chunk& chunk) {
+bool LoadedArsc::LoadTable(const Chunk& chunk, bool load_as_shared_library) {
   ATRACE_CALL();
   const ResTable_header* header = chunk.header<ResTable_header>();
   if (header == nullptr) {
@@ -520,10 +548,15 @@
         }
         packages_seen++;
 
-        std::unique_ptr<LoadedPackage> loaded_package = util::make_unique<LoadedPackage>();
-        if (!LoadPackage(child_chunk, loaded_package.get())) {
+        std::unique_ptr<LoadedPackage> loaded_package = LoadedPackage::Load(child_chunk);
+        if (!loaded_package) {
           return false;
         }
+
+        // Mark the package as dynamic if we are forcefully loading the Apk as a shared library.
+        if (loaded_package->package_id_ == kAppPackageId) {
+          loaded_package->dynamic_ = load_as_shared_library;
+        }
         packages_.push_back(std::move(loaded_package));
       } break;
 
@@ -540,7 +573,8 @@
   return true;
 }
 
-std::unique_ptr<LoadedArsc> LoadedArsc::Load(const void* data, size_t len) {
+std::unique_ptr<LoadedArsc> LoadedArsc::Load(const void* data, size_t len,
+                                             bool load_as_shared_library) {
   ATRACE_CALL();
 
   // Not using make_unique because the constructor is private.
@@ -551,7 +585,7 @@
     const Chunk chunk = iter.Next();
     switch (chunk.type()) {
       case RES_TABLE_TYPE:
-        if (!loaded_arsc->LoadTable(chunk)) {
+        if (!loaded_arsc->LoadTable(chunk, load_as_shared_library)) {
           return {};
         }
         break;
diff --git a/libs/androidfw/Util.cpp b/libs/androidfw/Util.cpp
new file mode 100644
index 0000000..202bc8e
--- /dev/null
+++ b/libs/androidfw/Util.cpp
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#include "androidfw/Util.h"
+
+#include <string>
+
+#include "utils/ByteOrder.h"
+#include "utils/Unicode.h"
+
+#ifdef _WIN32
+#ifdef ERROR
+#undef ERROR
+#endif
+#endif
+
+namespace android {
+namespace util {
+
+void ReadUtf16StringFromDevice(const uint16_t* src, size_t len, std::string* out) {
+  char buf[5];
+  while (*src && len != 0) {
+    char16_t c = static_cast<char16_t>(dtohs(*src));
+    utf16_to_utf8(&c, 1, buf, sizeof(buf));
+    out->append(buf, strlen(buf));
+    ++src;
+    --len;
+  }
+}
+
+} // namespace util
+} // namespace android
diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h
index a3d67f0..9d4fd29 100644
--- a/libs/androidfw/include/androidfw/ApkAssets.h
+++ b/libs/androidfw/include/androidfw/ApkAssets.h
@@ -32,6 +32,7 @@
 class ApkAssets {
  public:
   static std::unique_ptr<ApkAssets> Load(const std::string& path);
+  static std::unique_ptr<ApkAssets> LoadAsSharedLibrary(const std::string& path);
 
   std::unique_ptr<Asset> Open(const std::string& path,
                               Asset::AccessMode mode = Asset::AccessMode::ACCESS_RANDOM) const;
@@ -43,6 +44,8 @@
  private:
   DISALLOW_COPY_AND_ASSIGN(ApkAssets);
 
+  static std::unique_ptr<ApkAssets> LoadImpl(const std::string& path, bool load_as_shared_library);
+
   ApkAssets() = default;
 
   struct ZipArchivePtrCloser {
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index 66d5034..8655339 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -19,6 +19,7 @@
 
 #include "android-base/macros.h"
 
+#include <array>
 #include <limits>
 #include <unordered_map>
 
@@ -95,18 +96,21 @@
   // new resource IDs.
   bool SetApkAssets(const std::vector<const ApkAssets*>& apk_assets, bool invalidate_caches = true);
 
-  const std::vector<const ApkAssets*> GetApkAssets() const;
+  inline const std::vector<const ApkAssets*> GetApkAssets() const { return apk_assets_; }
 
   // Returns the string pool for the given asset cookie.
   // Use the string pool returned here with a valid Res_value object of
   // type Res_value::TYPE_STRING.
   const ResStringPool* GetStringPoolForCookie(ApkAssetsCookie cookie) const;
 
+  // Returns the DynamicRefTable for the given package ID.
+  const DynamicRefTable* GetDynamicRefTableForPackage(uint32_t package_id) const;
+
   // Sets/resets the configuration for this AssetManager. This will cause all
   // caches that are related to the configuration change to be invalidated.
   void SetConfiguration(const ResTable_config& configuration);
 
-  const ResTable_config& GetConfiguration() const;
+  inline const ResTable_config& GetConfiguration() const { return configuration_; }
 
   // Searches the set of APKs loaded by this AssetManager and opens the first one found located
   // in the assets/ directory.
@@ -173,6 +177,8 @@
   // Creates a new Theme from this AssetManager.
   std::unique_ptr<Theme> NewTheme();
 
+  void DumpToLog() const;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(AssetManager2);
 
@@ -189,9 +195,13 @@
   // `out_flags` stores the resulting bitmask of configuration axis with which the resource
   // value varies.
   ApkAssetsCookie FindEntry(uint32_t resid, uint16_t density_override, bool stop_at_first_match,
-                            LoadedArsc::Entry* out_entry, ResTable_config* out_selected_config,
+                            LoadedArscEntry* out_entry, ResTable_config* out_selected_config,
                             uint32_t* out_flags);
 
+  // Assigns package IDs to all shared library ApkAssets.
+  // Should be called whenever the ApkAssets are changed.
+  void BuildDynamicRefTable();
+
   // Purge all resources that are cached and vary by the configuration axis denoted by the
   // bitmask `diff`.
   void InvalidateCaches(uint32_t diff);
@@ -200,6 +210,22 @@
   // have a longer lifetime.
   std::vector<const ApkAssets*> apk_assets_;
 
+  struct PackageGroup {
+    std::vector<const LoadedPackage*> packages_;
+    std::vector<ApkAssetsCookie> cookies_;
+    DynamicRefTable dynamic_ref_table;
+  };
+
+  // DynamicRefTables for shared library package resolution.
+  // These are ordered according to apk_assets_. The mappings may change depending on what is
+  // in apk_assets_, therefore they must be stored in the AssetManager and not in the
+  // immutable ApkAssets class.
+  std::vector<PackageGroup> package_groups_;
+
+  // An array mapping package ID to index into package_groups. This keeps the lookup fast
+  // without taking too much memory.
+  std::array<uint8_t, std::numeric_limits<uint8_t>::max() + 1> package_ids_;
+
   // The current configuration set for this AssetManager. When this changes, cached resources
   // may need to be purged.
   ResTable_config configuration_;
@@ -279,12 +305,12 @@
   struct Package {
     // Each element of Type will be a dynamically sized object
     // allocated to have the entries stored contiguously with the Type.
-    util::unique_cptr<Type> types[kTypeCount];
+    std::array<util::unique_cptr<Type>, kTypeCount> types;
   };
 
   AssetManager2* asset_manager_;
   uint32_t type_spec_flags_ = 0u;
-  std::unique_ptr<Package> packages_[kPackageCount];
+  std::array<std::unique_ptr<Package>, kPackageCount> packages_;
 };
 
 inline const ResolvedBag::Entry* begin(const ResolvedBag* bag) { return bag->entries; }
diff --git a/libs/androidfw/Chunk.h b/libs/androidfw/include/androidfw/Chunk.h
similarity index 100%
rename from libs/androidfw/Chunk.h
rename to libs/androidfw/include/androidfw/Chunk.h
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index e2e56c8..8362008 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -22,12 +22,82 @@
 
 #include "android-base/macros.h"
 
+#include "androidfw/ByteBucketArray.h"
+#include "androidfw/Chunk.h"
 #include "androidfw/ResourceTypes.h"
+#include "androidfw/Util.h"
 
 namespace android {
 
-class Chunk;
-class LoadedPackage;
+class DynamicPackageEntry {
+ public:
+  DynamicPackageEntry() = default;
+  DynamicPackageEntry(std::string&& package_name, int package_id)
+      : package_name(std::move(package_name)), package_id(package_id) {}
+
+  std::string package_name;
+  int package_id = 0;
+};
+
+struct LoadedArscEntry {
+  // A pointer to the resource table entry for this resource.
+  // If the size of the entry is > sizeof(ResTable_entry), it can be cast to
+  // a ResTable_map_entry and processed as a bag/map.
+  const ResTable_entry* entry = nullptr;
+
+  // The dynamic package ID map for the package from which this resource came from.
+  const DynamicRefTable* dynamic_ref_table = nullptr;
+
+  // The string pool reference to the type's name. This uses a different string pool than
+  // the global string pool, but this is hidden from the caller.
+  StringPoolRef type_string_ref;
+
+  // The string pool reference to the entry's name. This uses a different string pool than
+  // the global string pool, but this is hidden from the caller.
+  StringPoolRef entry_string_ref;
+};
+
+struct TypeSpec;
+class LoadedArsc;
+
+class LoadedPackage {
+  friend class LoadedArsc;
+
+ public:
+  bool FindEntry(uint8_t type_idx, uint16_t entry_idx, const ResTable_config& config,
+                 LoadedArscEntry* out_entry, ResTable_config* out_selected_config,
+                 uint32_t* out_flags) const;
+
+  inline const ResStringPool* GetTypeStringPool() const { return &type_string_pool_; }
+
+  inline const ResStringPool* GetKeyStringPool() const { return &key_string_pool_; }
+
+  inline const std::string& GetPackageName() const { return package_name_; }
+
+  inline int GetPackageId() const { return package_id_; }
+
+  inline bool IsDynamic() const { return dynamic_; }
+
+  inline const std::vector<DynamicPackageEntry>& GetDynamicPackageMap() const {
+    return dynamic_package_map_;
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(LoadedPackage);
+
+  static std::unique_ptr<LoadedPackage> Load(const Chunk& chunk);
+
+  LoadedPackage() = default;
+
+  ResStringPool type_string_pool_;
+  ResStringPool key_string_pool_;
+  std::string package_name_;
+  int package_id_ = -1;
+  bool dynamic_ = false;
+
+  ByteBucketArray<util::unique_cptr<TypeSpec>> type_specs_;
+  std::vector<DynamicPackageEntry> dynamic_package_map_;
+};
 
 // Read-only view into a resource table. This class validates all data
 // when loading, including offsets and lengths.
@@ -35,7 +105,8 @@
  public:
   // Load the resource table from memory. The data's lifetime must out-live the
   // object returned from this method.
-  static std::unique_ptr<LoadedArsc> Load(const void* data, size_t len);
+  static std::unique_ptr<LoadedArsc> Load(const void* data, size_t len,
+                                          bool load_as_shared_library = false);
 
   ~LoadedArsc();
 
@@ -43,39 +114,28 @@
   // (Res_value::dataType == Res_value::TYPE_STRING) are indexed.
   inline const ResStringPool* GetStringPool() const { return &global_string_pool_; }
 
-  struct Entry {
-    // A pointer to the resource table entry for this resource.
-    // If the size of the entry is > sizeof(ResTable_entry), it can be cast to
-    // a ResTable_map_entry and processed as a bag/map.
-    const ResTable_entry* entry = nullptr;
-
-    // The string pool reference to the type's name. This uses a different string pool than
-    // the global string pool, but this is hidden from the caller.
-    StringPoolRef type_string_ref;
-
-    // The string pool reference to the entry's name. This uses a different string pool than
-    // the global string pool, but this is hidden from the caller.
-    StringPoolRef entry_string_ref;
-  };
-
   // Finds the resource with ID `resid` with the best value for configuration `config`.
   // The parameter `out_entry` will be filled with the resulting resource entry.
   // The resource entry can be a simple entry (ResTable_entry) or a complex bag
   // (ResTable_entry_map).
-  bool FindEntry(uint32_t resid, const ResTable_config& config, Entry* out_entry,
+  bool FindEntry(uint32_t resid, const ResTable_config& config, LoadedArscEntry* out_entry,
                  ResTable_config* selected_config, uint32_t* out_flags) const;
 
   // Gets a pointer to the name of the package in `resid`, or nullptr if the package doesn't exist.
-  const std::string* GetPackageNameForId(uint32_t resid) const;
+  const LoadedPackage* GetPackageForId(uint32_t resid) const;
+
+  inline const std::vector<std::unique_ptr<const LoadedPackage>>& GetPackages() const {
+    return packages_;
+  }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(LoadedArsc);
 
   LoadedArsc() = default;
-  bool LoadTable(const Chunk& chunk);
+  bool LoadTable(const Chunk& chunk, bool load_as_shared_library);
 
   ResStringPool global_string_pool_;
-  std::vector<std::unique_ptr<LoadedPackage>> packages_;
+  std::vector<std::unique_ptr<const LoadedPackage>> packages_;
 };
 
 }  // namespace android
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index 86ab123..56c22e6 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1538,6 +1538,8 @@
     uint16_t packageName[128];
 };
 
+class AssetManager2;
+
 /**
  * Holds the shared library ID table. Shared libraries are assigned package IDs at
  * build time, but they may be loaded in a different order, so we need to maintain
@@ -1548,7 +1550,9 @@
  */
 class DynamicRefTable
 {
+    friend class AssetManager2;
 public:
+    DynamicRefTable() = default;
     DynamicRefTable(uint8_t packageId, bool appAsLib);
 
     // Loads an unmapped reference table from the package.
@@ -1563,18 +1567,18 @@
 
     // Performs the actual conversion of build-time resource ID to run-time
     // resource ID.
-    inline status_t lookupResourceId(uint32_t* resId) const;
-    inline status_t lookupResourceValue(Res_value* value) const;
+    status_t lookupResourceId(uint32_t* resId) const;
+    status_t lookupResourceValue(Res_value* value) const;
 
     inline const KeyedVector<String16, uint8_t>& entries() const {
         return mEntries;
     }
 
 private:
-    const uint8_t                   mAssignedPackageId;
+    uint8_t                         mAssignedPackageId = 0;
     uint8_t                         mLookupTable[256];
     KeyedVector<String16, uint8_t>  mEntries;
-    bool                            mAppAsLib;
+    bool                            mAppAsLib = false;
 };
 
 bool U16StringToInt(const char16_t* s, size_t len, Res_value* outValue);
diff --git a/libs/androidfw/include/androidfw/Util.h b/libs/androidfw/include/androidfw/Util.h
index 5266d09..fd96730 100644
--- a/libs/androidfw/include/androidfw/Util.h
+++ b/libs/androidfw/include/androidfw/Util.h
@@ -102,6 +102,10 @@
   pointer ptr_;
 };
 
+inline uint32_t fix_package_id(uint32_t resid, uint8_t package_id) {
+  return resid | (static_cast<uint32_t>(package_id) << 24);
+}
+
 inline uint8_t get_package_id(uint32_t resid) {
   return static_cast<uint8_t>((resid >> 24) & 0x000000ffu);
 }
@@ -113,7 +117,7 @@
 
 inline uint16_t get_entry_id(uint32_t resid) { return static_cast<uint16_t>(resid & 0x0000ffffu); }
 
-inline bool is_internal_id(uint32_t resid) {
+inline bool is_internal_resid(uint32_t resid) {
   return (resid & 0xffff0000u) != 0 && (resid & 0x00ff0000u) == 0;
 }
 
@@ -121,6 +125,8 @@
   return (resid & 0x00ff0000u) != 0 && (resid & 0xff000000u) != 0;
 }
 
+void ReadUtf16StringFromDevice(const uint16_t* src, size_t len, std::string* out);
+
 }  // namespace util
 }  // namespace android
 
diff --git a/libs/androidfw/tests/ApkAssets_test.cpp b/libs/androidfw/tests/ApkAssets_test.cpp
index 3a1fc8f..0203712 100644
--- a/libs/androidfw/tests/ApkAssets_test.cpp
+++ b/libs/androidfw/tests/ApkAssets_test.cpp
@@ -26,9 +26,28 @@
 TEST(ApkAssetsTest, LoadApk) {
   std::unique_ptr<ApkAssets> loaded_apk = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
   ASSERT_NE(nullptr, loaded_apk);
+  EXPECT_NE(nullptr, loaded_apk->GetLoadedArsc());
 
   std::unique_ptr<Asset> asset = loaded_apk->Open("res/layout/main.xml");
   ASSERT_NE(nullptr, asset);
 }
 
+TEST(ApkAssetsTest, LoadApkAsSharedLibrary) {
+  std::unique_ptr<ApkAssets> loaded_apk =
+      ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk");
+  ASSERT_NE(nullptr, loaded_apk);
+  const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc();
+  ASSERT_NE(nullptr, loaded_arsc);
+  ASSERT_EQ(1u, loaded_arsc->GetPackages().size());
+  EXPECT_FALSE(loaded_arsc->GetPackages()[0]->IsDynamic());
+
+  loaded_apk = ApkAssets::LoadAsSharedLibrary(GetTestDataPath() + "/appaslib/appaslib.apk");
+  ASSERT_NE(nullptr, loaded_apk);
+
+  loaded_arsc = loaded_apk->GetLoadedArsc();
+  ASSERT_NE(nullptr, loaded_arsc);
+  ASSERT_EQ(1u, loaded_arsc->GetPackages().size());
+  EXPECT_TRUE(loaded_arsc->GetPackages()[0]->IsDynamic());
+}
+
 }  // namespace android
diff --git a/libs/androidfw/tests/AssetManager2_bench.cpp b/libs/androidfw/tests/AssetManager2_bench.cpp
index 9ff9478..b3c2dc3 100644
--- a/libs/androidfw/tests/AssetManager2_bench.cpp
+++ b/libs/androidfw/tests/AssetManager2_bench.cpp
@@ -16,6 +16,7 @@
 
 #include "benchmark/benchmark.h"
 
+#include "android-base/stringprintf.h"
 #include "androidfw/ApkAssets.h"
 #include "androidfw/AssetManager.h"
 #include "androidfw/AssetManager2.h"
@@ -23,10 +24,12 @@
 
 #include "TestHelpers.h"
 #include "data/basic/R.h"
+#include "data/libclient/R.h"
 #include "data/styles/R.h"
 
-namespace basic = com::android::basic;
 namespace app = com::android::app;
+namespace basic = com::android::basic;
+namespace libclient = com::android::libclient;
 
 namespace android {
 
@@ -78,101 +81,108 @@
 }
 BENCHMARK(BM_AssetManagerLoadFrameworkAssetsOld);
 
-static void BM_AssetManagerGetResource(benchmark::State& state) {
-  std::unique_ptr<ApkAssets> apk = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
-  if (apk == nullptr) {
-    state.SkipWithError("Failed to load assets");
-    return;
+static void GetResourceBenchmark(const std::vector<std::string>& paths,
+                                 const ResTable_config* config, uint32_t resid,
+                                 benchmark::State& state) {
+  std::vector<std::unique_ptr<ApkAssets>> apk_assets;
+  std::vector<const ApkAssets*> apk_assets_ptrs;
+  for (const std::string& path : paths) {
+    std::unique_ptr<ApkAssets> apk = ApkAssets::Load(path);
+    if (apk == nullptr) {
+      state.SkipWithError(base::StringPrintf("Failed to load assets %s", path.c_str()).c_str());
+      return;
+    }
+    apk_assets_ptrs.push_back(apk.get());
+    apk_assets.push_back(std::move(apk));
   }
 
-  AssetManager2 assets;
-  assets.SetApkAssets({apk.get()});
+  AssetManager2 assetmanager;
+  assetmanager.SetApkAssets(apk_assets_ptrs);
+  if (config != nullptr) {
+    assetmanager.SetConfiguration(*config);
+  }
 
   Res_value value;
   ResTable_config selected_config;
   uint32_t flags;
 
   while (state.KeepRunning()) {
-    assets.GetResource(basic::R::integer::number1, false /* may_be_bag */,
-                       0u /* density_override */, &value, &selected_config, &flags);
+    assetmanager.GetResource(resid, false /* may_be_bag */, 0u /* density_override */, &value,
+                             &selected_config, &flags);
   }
 }
+
+static void GetResourceBenchmarkOld(const std::vector<std::string>& paths,
+                                    const ResTable_config* config, uint32_t resid,
+                                    benchmark::State& state) {
+  AssetManager assetmanager;
+  for (const std::string& path : paths) {
+    if (!assetmanager.addAssetPath(String8(path.c_str()), nullptr /* cookie */,
+                                   false /* appAsLib */, false /* isSystemAssets */)) {
+      state.SkipWithError(base::StringPrintf("Failed to load assets %s", path.c_str()).c_str());
+      return;
+    }
+  }
+
+  if (config != nullptr) {
+    assetmanager.setConfiguration(*config);
+  }
+
+  const ResTable& table = assetmanager.getResources(true);
+
+  Res_value value;
+  ResTable_config selected_config;
+  uint32_t flags;
+
+  while (state.KeepRunning()) {
+    table.getResource(resid, &value, false /*may_be_bag*/, 0u /*density*/, &flags,
+                      &selected_config);
+  }
+}
+
+static void BM_AssetManagerGetResource(benchmark::State& state) {
+  GetResourceBenchmark({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/,
+                       basic::R::integer::number1, state);
+}
 BENCHMARK(BM_AssetManagerGetResource);
 
 static void BM_AssetManagerGetResourceOld(benchmark::State& state) {
-  AssetManager assets;
-  if (!assets.addAssetPath(String8((GetTestDataPath() + "/basic/basic.apk").data()),
-                           nullptr /* cookie */, false /* appAsLib */,
-                           false /* isSystemAssets */)) {
-    state.SkipWithError("Failed to load assets");
-    return;
-  }
-
-  const ResTable& table = assets.getResources(true);
-
-  Res_value value;
-  ResTable_config selected_config;
-  uint32_t flags;
-
-  while (state.KeepRunning()) {
-    table.getResource(basic::R::integer::number1, &value, false /* may_be_bag */,
-                      0u /* density_override */, &flags, &selected_config);
-  }
+  GetResourceBenchmarkOld({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/,
+                          basic::R::integer::number1, state);
 }
 BENCHMARK(BM_AssetManagerGetResourceOld);
 
+static void BM_AssetManagerGetLibraryResource(benchmark::State& state) {
+  GetResourceBenchmark(
+      {GetTestDataPath() + "/lib_two/lib_two.apk", GetTestDataPath() + "/lib_one/lib_one.apk",
+       GetTestDataPath() + "/libclient/libclient.apk"},
+      nullptr /*config*/, libclient::R::string::foo_one, state);
+}
+BENCHMARK(BM_AssetManagerGetLibraryResource);
+
+static void BM_AssetManagerGetLibraryResourceOld(benchmark::State& state) {
+  GetResourceBenchmarkOld(
+      {GetTestDataPath() + "/lib_two/lib_two.apk", GetTestDataPath() + "/lib_one/lib_one.apk",
+       GetTestDataPath() + "/libclient/libclient.apk"},
+      nullptr /*config*/, libclient::R::string::foo_one, state);
+}
+BENCHMARK(BM_AssetManagerGetLibraryResourceOld);
+
 constexpr static const uint32_t kStringOkId = 0x0104000au;
 
 static void BM_AssetManagerGetResourceFrameworkLocale(benchmark::State& state) {
-  std::unique_ptr<ApkAssets> apk = ApkAssets::Load(kFrameworkPath);
-  if (apk == nullptr) {
-    state.SkipWithError("Failed to load assets");
-    return;
-  }
-
-  AssetManager2 assets;
-  assets.SetApkAssets({apk.get()});
-
   ResTable_config config;
   memset(&config, 0, sizeof(config));
   memcpy(config.language, "fr", 2);
-  assets.SetConfiguration(config);
-
-  Res_value value;
-  ResTable_config selected_config;
-  uint32_t flags;
-
-  while (state.KeepRunning()) {
-    assets.GetResource(kStringOkId, false /* may_be_bag */, 0u /* density_override */, &value,
-                       &selected_config, &flags);
-  }
+  GetResourceBenchmark({kFrameworkPath}, &config, kStringOkId, state);
 }
 BENCHMARK(BM_AssetManagerGetResourceFrameworkLocale);
 
 static void BM_AssetManagerGetResourceFrameworkLocaleOld(benchmark::State& state) {
-  AssetManager assets;
-  if (!assets.addAssetPath(String8((GetTestDataPath() + "/basic/basic.apk").data()),
-                           nullptr /* cookie */, false /* appAsLib */,
-                           false /* isSystemAssets */)) {
-    state.SkipWithError("Failed to load assets");
-    return;
-  }
-
   ResTable_config config;
   memset(&config, 0, sizeof(config));
   memcpy(config.language, "fr", 2);
-  assets.setConfiguration(config, nullptr);
-
-  const ResTable& table = assets.getResources(true);
-
-  Res_value value;
-  ResTable_config selected_config;
-  uint32_t flags;
-
-  while (state.KeepRunning()) {
-    table.getResource(kStringOkId, &value, false /* may_be_bag */, 0u /* density_override */,
-                      &flags, &selected_config);
-  }
+  GetResourceBenchmarkOld({kFrameworkPath}, &config, kStringOkId, state);
 }
 BENCHMARK(BM_AssetManagerGetResourceFrameworkLocaleOld);
 
@@ -202,8 +212,7 @@
 static void BM_AssetManagerGetBagOld(benchmark::State& state) {
   AssetManager assets;
   if (!assets.addAssetPath(String8((GetTestDataPath() + "/styles/styles.apk").data()),
-                           nullptr /* cookie */, false /* appAsLib */,
-                           false /* isSystemAssets */)) {
+                           nullptr /*cookie*/, false /*appAsLib*/, false /*isSystemAssets*/)) {
     state.SkipWithError("Failed to load assets");
     return;
   }
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index 39c5381..543456a 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -20,11 +20,19 @@
 #include "android-base/logging.h"
 
 #include "TestHelpers.h"
+#include "data/appaslib/R.h"
 #include "data/basic/R.h"
+#include "data/lib_one/R.h"
+#include "data/lib_two/R.h"
+#include "data/libclient/R.h"
 #include "data/styles/R.h"
 
-namespace basic = com::android::basic;
 namespace app = com::android::app;
+namespace appaslib = com::android::appaslib::app;
+namespace basic = com::android::basic;
+namespace lib_one = com::android::lib_one;
+namespace lib_two = com::android::lib_two;
+namespace libclient = com::android::libclient;
 
 namespace android {
 
@@ -39,15 +47,31 @@
 
     style_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
     ASSERT_NE(nullptr, style_assets_);
+
+    lib_one_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_one/lib_one.apk");
+    ASSERT_NE(nullptr, lib_one_assets_);
+
+    lib_two_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_two/lib_two.apk");
+    ASSERT_NE(nullptr, lib_two_assets_);
+
+    libclient_assets_ = ApkAssets::Load(GetTestDataPath() + "/libclient/libclient.apk");
+    ASSERT_NE(nullptr, libclient_assets_);
+
+    appaslib_assets_ = ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk");
+    ASSERT_NE(nullptr, appaslib_assets_);
   }
 
  protected:
   std::unique_ptr<ApkAssets> basic_assets_;
   std::unique_ptr<ApkAssets> basic_de_fr_assets_;
   std::unique_ptr<ApkAssets> style_assets_;
+  std::unique_ptr<ApkAssets> lib_one_assets_;
+  std::unique_ptr<ApkAssets> lib_two_assets_;
+  std::unique_ptr<ApkAssets> libclient_assets_;
+  std::unique_ptr<ApkAssets> appaslib_assets_;
 };
 
-TEST_F(AssetManager2Test, FindsResourcesFromSingleApkAssets) {
+TEST_F(AssetManager2Test, FindsResourceFromSingleApkAssets) {
   ResTable_config desired_config;
   memset(&desired_config, 0, sizeof(desired_config));
   desired_config.language[0] = 'd';
@@ -77,7 +101,7 @@
   EXPECT_EQ(Res_value::TYPE_STRING, value.dataType);
 }
 
-TEST_F(AssetManager2Test, FindsResourcesFromMultipleApkAssets) {
+TEST_F(AssetManager2Test, FindsResourceFromMultipleApkAssets) {
   ResTable_config desired_config;
   memset(&desired_config, 0, sizeof(desired_config));
   desired_config.language[0] = 'd';
@@ -99,7 +123,7 @@
   // Came from our de_fr ApkAssets.
   EXPECT_EQ(1, cookie);
 
-  // The configuration is german.
+  // The configuration is German.
   EXPECT_EQ('d', selected_config.language[0]);
   EXPECT_EQ('e', selected_config.language[1]);
 
@@ -107,7 +131,72 @@
   EXPECT_EQ(Res_value::TYPE_STRING, value.dataType);
 }
 
-TEST_F(AssetManager2Test, FindsBagResourcesFromSingleApkAssets) {
+TEST_F(AssetManager2Test, FindsResourceFromSharedLibrary) {
+  AssetManager2 assetmanager;
+
+  // libclient is built with lib_one and then lib_two in order.
+  // Reverse the order to test that proper package ID re-assignment is happening.
+  assetmanager.SetApkAssets(
+      {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
+
+  Res_value value;
+  ResTable_config selected_config;
+  uint32_t flags;
+
+  ApkAssetsCookie cookie =
+      assetmanager.GetResource(libclient::R::string::foo_one, false /*may_be_bag*/,
+                               0 /*density_override*/, &value, &selected_config, &flags);
+  ASSERT_NE(kInvalidCookie, cookie);
+
+  // Reference comes from libclient.
+  EXPECT_EQ(2, cookie);
+  EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
+
+  // Lookup the reference.
+  cookie = assetmanager.GetResource(value.data, false /* may_be_bag */, 0 /* density_override*/,
+                                    &value, &selected_config, &flags);
+  ASSERT_NE(kInvalidCookie, cookie);
+  EXPECT_EQ(1, cookie);
+  EXPECT_EQ(Res_value::TYPE_STRING, value.dataType);
+  EXPECT_EQ(std::string("Foo from lib_one"),
+            GetStringFromPool(assetmanager.GetStringPoolForCookie(cookie), value.data));
+
+  cookie = assetmanager.GetResource(libclient::R::string::foo_two, false /*may_be_bag*/,
+                                    0 /*density_override*/, &value, &selected_config, &flags);
+  ASSERT_NE(kInvalidCookie, cookie);
+
+  // Reference comes from libclient.
+  EXPECT_EQ(2, cookie);
+  EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
+
+  // Lookup the reference.
+  cookie = assetmanager.GetResource(value.data, false /* may_be_bag */, 0 /* density_override*/,
+                                    &value, &selected_config, &flags);
+  ASSERT_NE(kInvalidCookie, cookie);
+  EXPECT_EQ(0, cookie);
+  EXPECT_EQ(Res_value::TYPE_STRING, value.dataType);
+  EXPECT_EQ(std::string("Foo from lib_two"),
+            GetStringFromPool(assetmanager.GetStringPoolForCookie(cookie), value.data));
+}
+
+TEST_F(AssetManager2Test, FindsResourceFromAppLoadedAsSharedLibrary) {
+  AssetManager2 assetmanager;
+  assetmanager.SetApkAssets({appaslib_assets_.get()});
+
+  // The appaslib package will have been assigned the package ID 0x02.
+
+  Res_value value;
+  ResTable_config selected_config;
+  uint32_t flags;
+  ApkAssetsCookie cookie = assetmanager.GetResource(
+      util::fix_package_id(appaslib::R::integer::number1, 0x02), false /*may_be_bag*/,
+      0u /*density_override*/, &value, &selected_config, &flags);
+  ASSERT_NE(kInvalidCookie, cookie);
+  EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
+  EXPECT_EQ(util::fix_package_id(appaslib::R::array::integerArray1, 0x02), value.data);
+}
+
+TEST_F(AssetManager2Test, FindsBagResourceFromSingleApkAssets) {
   AssetManager2 assetmanager;
   assetmanager.SetApkAssets({basic_assets_.get()});
 
@@ -128,6 +217,27 @@
   EXPECT_EQ(0, bag->entries[2].cookie);
 }
 
+TEST_F(AssetManager2Test, FindsBagResourceFromMultipleApkAssets) {}
+
+TEST_F(AssetManager2Test, FindsBagResourceFromSharedLibrary) {
+  AssetManager2 assetmanager;
+
+  // libclient is built with lib_one and then lib_two in order.
+  // Reverse the order to test that proper package ID re-assignment is happening.
+  assetmanager.SetApkAssets(
+      {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
+
+  const ResolvedBag* bag = assetmanager.GetBag(libclient::R::style::Theme);
+  ASSERT_NE(nullptr, bag);
+  ASSERT_GE(bag->entry_count, 2u);
+
+  // First two attributes come from lib_one.
+  EXPECT_EQ(1, bag->entries[0].cookie);
+  EXPECT_EQ(0x03, util::get_package_id(bag->entries[0].key));
+  EXPECT_EQ(1, bag->entries[1].cookie);
+  EXPECT_EQ(0x03, util::get_package_id(bag->entries[1].key));
+}
+
 TEST_F(AssetManager2Test, MergesStylesWithParentFromSingleApkAssets) {
   AssetManager2 assetmanager;
   assetmanager.SetApkAssets({style_assets_.get()});
@@ -181,8 +291,6 @@
   EXPECT_EQ(0, bag_two->entries[4].cookie);
 }
 
-TEST_F(AssetManager2Test, FindsBagResourcesFromMultipleApkAssets) {}
-
 TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) {}
 
 TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) {}
diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp
index 47b3894..045507e 100644
--- a/libs/androidfw/tests/LoadedArsc_test.cpp
+++ b/libs/androidfw/tests/LoadedArsc_test.cpp
@@ -16,21 +16,18 @@
 
 #include "androidfw/LoadedArsc.h"
 
-#include "android-base/file.h"
-#include "android-base/logging.h"
-#include "android-base/macros.h"
-
 #include "TestHelpers.h"
 #include "data/basic/R.h"
+#include "data/libclient/R.h"
 #include "data/styles/R.h"
 
 namespace app = com::android::app;
 namespace basic = com::android::basic;
+namespace libclient = com::android::libclient;
 
 namespace android {
 
 TEST(LoadedArscTest, LoadSinglePackageArsc) {
-  base::ScopedLogSeverity _log(base::LogSeverity::DEBUG);
   std::string contents;
   ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/styles/styles.apk", "resources.arsc",
                                       &contents));
@@ -38,11 +35,16 @@
   std::unique_ptr<LoadedArsc> loaded_arsc = LoadedArsc::Load(contents.data(), contents.size());
   ASSERT_NE(nullptr, loaded_arsc);
 
+  const std::vector<std::unique_ptr<const LoadedPackage>>& packages = loaded_arsc->GetPackages();
+  ASSERT_EQ(1u, packages.size());
+  EXPECT_EQ(std::string("com.android.app"), packages[0]->GetPackageName());
+  EXPECT_EQ(0x7f, packages[0]->GetPackageId());
+
   ResTable_config config;
   memset(&config, 0, sizeof(config));
   config.sdkVersion = 24;
 
-  LoadedArsc::Entry entry;
+  LoadedArscEntry entry;
   ResTable_config selected_config;
   uint32_t flags;
 
@@ -52,7 +54,6 @@
 }
 
 TEST(LoadedArscTest, FindDefaultEntry) {
-  base::ScopedLogSeverity _log(base::LogSeverity::DEBUG);
   std::string contents;
   ASSERT_TRUE(
       ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc", &contents));
@@ -65,7 +66,7 @@
   desired_config.language[0] = 'd';
   desired_config.language[1] = 'e';
 
-  LoadedArsc::Entry entry;
+  LoadedArscEntry entry;
   ResTable_config selected_config;
   uint32_t flags;
 
@@ -74,6 +75,70 @@
   ASSERT_NE(nullptr, entry.entry);
 }
 
+TEST(LoadedArscTest, LoadSharedLibrary) {
+  std::string contents;
+  ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/lib_one/lib_one.apk", "resources.arsc",
+                                      &contents));
+
+  std::unique_ptr<LoadedArsc> loaded_arsc = LoadedArsc::Load(contents.data(), contents.size());
+  ASSERT_NE(nullptr, loaded_arsc);
+
+  const auto& packages = loaded_arsc->GetPackages();
+  ASSERT_EQ(1u, packages.size());
+
+  EXPECT_TRUE(packages[0]->IsDynamic());
+  EXPECT_EQ(std::string("com.android.lib_one"), packages[0]->GetPackageName());
+  EXPECT_EQ(0, packages[0]->GetPackageId());
+
+  const auto& dynamic_pkg_map = packages[0]->GetDynamicPackageMap();
+
+  // The library has no dependencies.
+  ASSERT_TRUE(dynamic_pkg_map.empty());
+}
+
+TEST(LoadedArscTest, LoadAppLinkedAgainstSharedLibrary) {
+  std::string contents;
+  ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/libclient/libclient.apk",
+                                      "resources.arsc", &contents));
+
+  std::unique_ptr<LoadedArsc> loaded_arsc = LoadedArsc::Load(contents.data(), contents.size());
+  ASSERT_NE(nullptr, loaded_arsc);
+
+  const auto& packages = loaded_arsc->GetPackages();
+  ASSERT_EQ(1u, packages.size());
+
+  EXPECT_FALSE(packages[0]->IsDynamic());
+  EXPECT_EQ(std::string("com.android.libclient"), packages[0]->GetPackageName());
+  EXPECT_EQ(0x7f, packages[0]->GetPackageId());
+
+  const auto& dynamic_pkg_map = packages[0]->GetDynamicPackageMap();
+
+  // The library has two dependencies.
+  ASSERT_EQ(2u, dynamic_pkg_map.size());
+
+  EXPECT_EQ(std::string("com.android.lib_one"), dynamic_pkg_map[0].package_name);
+  EXPECT_EQ(0x02, dynamic_pkg_map[0].package_id);
+
+  EXPECT_EQ(std::string("com.android.lib_two"), dynamic_pkg_map[1].package_name);
+  EXPECT_EQ(0x03, dynamic_pkg_map[1].package_id);
+}
+
+TEST(LoadedArscTest, LoadAppAsSharedLibrary) {
+  std::string contents;
+  ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/appaslib/appaslib.apk",
+                                      "resources.arsc", &contents));
+
+  std::unique_ptr<LoadedArsc> loaded_arsc =
+      LoadedArsc::Load(contents.data(), contents.size(), true /*load_as_shared_library*/);
+  ASSERT_NE(nullptr, loaded_arsc);
+
+  const auto& packages = loaded_arsc->GetPackages();
+  ASSERT_EQ(1u, packages.size());
+
+  EXPECT_TRUE(packages[0]->IsDynamic());
+  EXPECT_EQ(0x7f, packages[0]->GetPackageId());
+}
+
 // structs with size fields (like Res_value, ResTable_entry) should be
 // backwards and forwards compatible (aka checking the size field against
 // sizeof(Res_value) might not be backwards compatible.
diff --git a/libs/androidfw/tests/ResTable_test.cpp b/libs/androidfw/tests/ResTable_test.cpp
index b151f3f..ad1cd2b 100644
--- a/libs/androidfw/tests/ResTable_test.cpp
+++ b/libs/androidfw/tests/ResTable_test.cpp
@@ -25,10 +25,10 @@
 
 #include "TestHelpers.h"
 #include "data/basic/R.h"
-#include "data/lib/R.h"
+#include "data/lib_one/R.h"
 
 namespace basic = com::android::basic;
-namespace lib = com::android::lib;
+namespace lib = com::android::lib_one;
 
 namespace android {
 
@@ -119,7 +119,7 @@
 
 TEST(ResTableTest, LibraryThemeIsAppliedCorrectly) {
   std::string contents;
-  ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/lib/lib.apk",
+  ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/lib_one/lib_one.apk",
                                       "resources.arsc", &contents));
 
   ResTable table;
diff --git a/libs/androidfw/tests/Theme_test.cpp b/libs/androidfw/tests/Theme_test.cpp
index c0011b6d..59cb18a 100644
--- a/libs/androidfw/tests/Theme_test.cpp
+++ b/libs/androidfw/tests/Theme_test.cpp
@@ -19,9 +19,13 @@
 #include "android-base/logging.h"
 
 #include "TestHelpers.h"
+#include "data/lib_one/R.h"
+#include "data/libclient/R.h"
 #include "data/styles/R.h"
 
 namespace app = com::android::app;
+namespace lib_one = com::android::lib_one;
+namespace libclient = com::android::libclient;
 
 namespace android {
 
@@ -30,10 +34,22 @@
   void SetUp() override {
     style_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
     ASSERT_NE(nullptr, style_assets_);
+
+    libclient_assets_ = ApkAssets::Load(GetTestDataPath() + "/libclient/libclient.apk");
+    ASSERT_NE(nullptr, libclient_assets_);
+
+    lib_one_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_one/lib_one.apk");
+    ASSERT_NE(nullptr, lib_one_assets_);
+
+    lib_two_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_two/lib_two.apk");
+    ASSERT_NE(nullptr, lib_two_assets_);
   }
 
  protected:
   std::unique_ptr<ApkAssets> style_assets_;
+  std::unique_ptr<ApkAssets> libclient_assets_;
+  std::unique_ptr<ApkAssets> lib_one_assets_;
+  std::unique_ptr<ApkAssets> lib_two_assets_;
 };
 
 TEST_F(ThemeTest, EmptyTheme) {
@@ -174,6 +190,36 @@
   EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
 }
 
+TEST_F(ThemeTest, ResolveDynamicAttributesAndReferencesToSharedLibrary) {
+  AssetManager2 assetmanager;
+  assetmanager.SetApkAssets(
+      {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
+
+  std::unique_ptr<Theme> theme = assetmanager.NewTheme();
+  ASSERT_TRUE(theme->ApplyStyle(libclient::R::style::Theme, false /*force*/));
+
+  Res_value value;
+  uint32_t flags;
+  ApkAssetsCookie cookie;
+
+  // The attribute should be resolved to the final value.
+  cookie = theme->GetAttribute(libclient::R::attr::foo, &value, &flags);
+  ASSERT_NE(kInvalidCookie, cookie);
+  EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
+  EXPECT_EQ(700u, value.data);
+  EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
+
+  // The reference should be resolved to a TYPE_REFERENCE.
+  cookie = theme->GetAttribute(libclient::R::attr::bar, &value, &flags);
+  ASSERT_NE(kInvalidCookie, cookie);
+  EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
+
+  // lib_one is assigned package ID 0x03.
+  EXPECT_EQ(3u, util::get_package_id(value.data));
+  EXPECT_EQ(util::get_type_id(lib_one::R::string::foo), util::get_type_id(value.data));
+  EXPECT_EQ(util::get_entry_id(lib_one::R::string::foo), util::get_entry_id(value.data));
+}
+
 TEST_F(ThemeTest, CopyThemeSameAssetManager) {
   AssetManager2 assetmanager;
   assetmanager.SetApkAssets({style_assets_.get()});
diff --git a/libs/androidfw/tests/data/lib/lib.apk b/libs/androidfw/tests/data/lib/lib.apk
deleted file mode 100644
index 44c27c7..0000000
--- a/libs/androidfw/tests/data/lib/lib.apk
+++ /dev/null
Binary files differ
diff --git a/libs/androidfw/tests/data/lib/AndroidManifest.xml b/libs/androidfw/tests/data/lib_one/AndroidManifest.xml
similarity index 95%
rename from libs/androidfw/tests/data/lib/AndroidManifest.xml
rename to libs/androidfw/tests/data/lib_one/AndroidManifest.xml
index 02f5d3e..860adf7 100644
--- a/libs/androidfw/tests/data/lib/AndroidManifest.xml
+++ b/libs/androidfw/tests/data/lib_one/AndroidManifest.xml
@@ -15,6 +15,6 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.lib">
+    package="com.android.lib_one">
     <application />
 </manifest>
diff --git a/libs/androidfw/tests/data/lib/R.h b/libs/androidfw/tests/data/lib_one/R.h
similarity index 80%
rename from libs/androidfw/tests/data/lib/R.h
rename to libs/androidfw/tests/data/lib_one/R.h
index bb22d22..fcaeb8d 100644
--- a/libs/androidfw/tests/data/lib/R.h
+++ b/libs/androidfw/tests/data/lib_one/R.h
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-#ifndef TEST_DATA_LIB_R_H_
-#define TEST_DATA_LIB_R_H_
+#ifndef TEST_DATA_LIB_ONE_R_H_
+#define TEST_DATA_LIB_ONE_R_H_
 
 #include <cstdint>
 
 namespace com {
 namespace android {
-namespace lib {
+namespace lib_one {
 
 struct R {
   struct attr {
@@ -36,10 +36,16 @@
       Theme = 0x02020000,  // default
     };
   };
+
+  struct string {
+    enum : uint32_t {
+      foo = 0x02030000,  // default
+    };
+  };
 };
 
-}  // namespace lib
+}  // namespace lib_one
 }  // namespace android
 }  // namespace com
 
-#endif  // TEST_DATA_R_H_
+#endif  // TEST_DATA_LIB_ONE_R_H_
diff --git a/libs/androidfw/tests/data/lib/build b/libs/androidfw/tests/data/lib_one/build
similarity index 89%
rename from libs/androidfw/tests/data/lib/build
rename to libs/androidfw/tests/data/lib_one/build
index 5c3d02c..c6adf0b 100755
--- a/libs/androidfw/tests/data/lib/build
+++ b/libs/androidfw/tests/data/lib_one/build
@@ -17,4 +17,4 @@
 
 set -e
 
-aapt package -M AndroidManifest.xml -S res -F lib.apk -f --shared-lib
+aapt package -M AndroidManifest.xml -S res -F lib_one.apk -f --shared-lib
diff --git a/libs/androidfw/tests/data/lib_one/lib_one.apk b/libs/androidfw/tests/data/lib_one/lib_one.apk
new file mode 100644
index 0000000..f287554
--- /dev/null
+++ b/libs/androidfw/tests/data/lib_one/lib_one.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/lib/res/values/values.xml b/libs/androidfw/tests/data/lib_one/res/values/values.xml
similarity index 66%
copy from libs/androidfw/tests/data/lib/res/values/values.xml
copy to libs/androidfw/tests/data/lib_one/res/values/values.xml
index 51e3a40..752b7e9 100644
--- a/libs/androidfw/tests/data/lib/res/values/values.xml
+++ b/libs/androidfw/tests/data/lib_one/res/values/values.xml
@@ -15,11 +15,18 @@
 -->
 
 <resources>
+    <public type="attr" name="attr1" id="0x00010000" />
     <attr name="attr1" format="integer" />
+
+    <public type="attr" name="attr2" id="0x00010001" />
     <attr name="attr2" format="integer" />
 
+    <public type="style" name="Theme" id="0x00020000" />
     <style name="Theme">
-        <item name="com.android.lib:attr1">700</item>
-        <item name="com.android.lib:attr2">?com.android.lib:attr1</item>
+        <item name="com.android.lib_one:attr1">700</item>
+        <item name="com.android.lib_one:attr2">?com.android.lib_one:attr1</item>
     </style>
+
+    <public type="string" name="foo" id="0x00030000" />
+    <string name="foo">Foo from lib_one</string>
 </resources>
diff --git a/libs/androidfw/tests/data/lib/AndroidManifest.xml b/libs/androidfw/tests/data/lib_two/AndroidManifest.xml
similarity index 87%
copy from libs/androidfw/tests/data/lib/AndroidManifest.xml
copy to libs/androidfw/tests/data/lib_two/AndroidManifest.xml
index 02f5d3e..4b131e5 100644
--- a/libs/androidfw/tests/data/lib/AndroidManifest.xml
+++ b/libs/androidfw/tests/data/lib_two/AndroidManifest.xml
@@ -14,7 +14,6 @@
      limitations under the License.
 -->
 
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.lib">
+<manifest package="com.android.lib_two">
     <application />
 </manifest>
diff --git a/libs/androidfw/tests/data/lib/R.h b/libs/androidfw/tests/data/lib_two/R.h
similarity index 72%
copy from libs/androidfw/tests/data/lib/R.h
copy to libs/androidfw/tests/data/lib_two/R.h
index bb22d22..c04a9d3 100644
--- a/libs/androidfw/tests/data/lib/R.h
+++ b/libs/androidfw/tests/data/lib_two/R.h
@@ -14,32 +14,26 @@
  * limitations under the License.
  */
 
-#ifndef TEST_DATA_LIB_R_H_
-#define TEST_DATA_LIB_R_H_
+#ifndef TEST_DATA_LIB_TWO_R_H_
+#define TEST_DATA_LIB_TWO_R_H_
 
 #include <cstdint>
 
 namespace com {
 namespace android {
-namespace lib {
+namespace lib_two {
 
 struct R {
-  struct attr {
+  struct string {
     enum : uint32_t {
-      attr1 = 0x02010000,  // default
-      attr2 = 0x02010001,  // default
-    };
-  };
-
-  struct style {
-    enum : uint32_t {
-      Theme = 0x02020000,  // default
+      LibraryString = 0x02020000,  // default
+      foo = 0x02020001, // default
     };
   };
 };
 
-}  // namespace lib
+}  // namespace lib_two
 }  // namespace android
 }  // namespace com
 
-#endif  // TEST_DATA_R_H_
+#endif  // TEST_DATA_LIB_TWO_R_H_
diff --git a/libs/androidfw/tests/data/lib/build b/libs/androidfw/tests/data/lib_two/build
similarity index 89%
copy from libs/androidfw/tests/data/lib/build
copy to libs/androidfw/tests/data/lib_two/build
index 5c3d02c..fd75e1d 100755
--- a/libs/androidfw/tests/data/lib/build
+++ b/libs/androidfw/tests/data/lib_two/build
@@ -17,4 +17,4 @@
 
 set -e
 
-aapt package -M AndroidManifest.xml -S res -F lib.apk -f --shared-lib
+aapt package -M AndroidManifest.xml -S res -F lib_two.apk -f --shared-lib
diff --git a/libs/androidfw/tests/data/lib_two/lib_two.apk b/libs/androidfw/tests/data/lib_two/lib_two.apk
new file mode 100644
index 0000000..ad44f9c
--- /dev/null
+++ b/libs/androidfw/tests/data/lib_two/lib_two.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/lib/res/values/values.xml b/libs/androidfw/tests/data/lib_two/res/values/values.xml
similarity index 73%
rename from libs/androidfw/tests/data/lib/res/values/values.xml
rename to libs/androidfw/tests/data/lib_two/res/values/values.xml
index 51e3a40..f4eea26 100644
--- a/libs/androidfw/tests/data/lib/res/values/values.xml
+++ b/libs/androidfw/tests/data/lib_two/res/values/values.xml
@@ -15,11 +15,9 @@
 -->
 
 <resources>
-    <attr name="attr1" format="integer" />
-    <attr name="attr2" format="integer" />
+    <public type="string" name="LibraryString" id="0x00020000" />
+    <string name="LibraryString">Hi from library two</string>
 
-    <style name="Theme">
-        <item name="com.android.lib:attr1">700</item>
-        <item name="com.android.lib:attr2">?com.android.lib:attr1</item>
-    </style>
+    <public type="string" name="foo" id="0x00020001" />
+    <string name="foo">Foo from lib_two</string>
 </resources>
diff --git a/libs/androidfw/tests/data/lib/AndroidManifest.xml b/libs/androidfw/tests/data/libclient/AndroidManifest.xml
similarity index 87%
copy from libs/androidfw/tests/data/lib/AndroidManifest.xml
copy to libs/androidfw/tests/data/libclient/AndroidManifest.xml
index 02f5d3e..8436383 100644
--- a/libs/androidfw/tests/data/lib/AndroidManifest.xml
+++ b/libs/androidfw/tests/data/libclient/AndroidManifest.xml
@@ -14,7 +14,6 @@
      limitations under the License.
 -->
 
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.lib">
+<manifest package="com.android.libclient">
     <application />
 </manifest>
diff --git a/libs/androidfw/tests/data/lib/R.h b/libs/androidfw/tests/data/libclient/R.h
similarity index 75%
copy from libs/androidfw/tests/data/lib/R.h
copy to libs/androidfw/tests/data/libclient/R.h
index bb22d22..43d1f9b 100644
--- a/libs/androidfw/tests/data/lib/R.h
+++ b/libs/androidfw/tests/data/libclient/R.h
@@ -21,24 +21,31 @@
 
 namespace com {
 namespace android {
-namespace lib {
+namespace libclient {
 
 struct R {
   struct attr {
     enum : uint32_t {
-      attr1 = 0x02010000,  // default
-      attr2 = 0x02010001,  // default
+      foo = 0x7f010000,  // default
+      bar = 0x7f010001,  // default
     };
   };
 
   struct style {
     enum : uint32_t {
-      Theme = 0x02020000,  // default
+      Theme = 0x7f020000,  // default
+    };
+  };
+
+  struct string {
+    enum : uint32_t {
+      foo_one = 0x7f030000,  // default
+      foo_two = 0x7f030001,  // default
     };
   };
 };
 
-}  // namespace lib
+}  // namespace libclient
 }  // namespace android
 }  // namespace com
 
diff --git a/libs/androidfw/tests/data/lib/build b/libs/androidfw/tests/data/libclient/build
similarity index 66%
copy from libs/androidfw/tests/data/lib/build
copy to libs/androidfw/tests/data/libclient/build
index 5c3d02c..08310e3 100755
--- a/libs/androidfw/tests/data/lib/build
+++ b/libs/androidfw/tests/data/libclient/build
@@ -17,4 +17,14 @@
 
 set -e
 
-aapt package -M AndroidManifest.xml -S res -F lib.apk -f --shared-lib
+PATH_TO_FRAMEWORK_RES=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/android.jar
+PATH_TO_LIB_ONE=../lib_one/lib_one.apk
+PATH_TO_LIB_TWO=../lib_two/lib_two.apk
+
+aapt package \
+    -M AndroidManifest.xml \
+    -S res \
+    -I $PATH_TO_FRAMEWORK_RES \
+    -I $PATH_TO_LIB_ONE \
+    -I $PATH_TO_LIB_TWO \
+    -F libclient.apk -f
diff --git a/libs/androidfw/tests/data/libclient/libclient.apk b/libs/androidfw/tests/data/libclient/libclient.apk
new file mode 100644
index 0000000..1799024
--- /dev/null
+++ b/libs/androidfw/tests/data/libclient/libclient.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/libclient/res/values/values.xml b/libs/androidfw/tests/data/libclient/res/values/values.xml
new file mode 100644
index 0000000..fead7c3
--- /dev/null
+++ b/libs/androidfw/tests/data/libclient/res/values/values.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+
+<resources>
+    <public type="attr" name="foo" id="0x7f010000" />
+    <attr name="foo" />
+
+    <public type="attr" name="bar" id="0x7f010001" />
+    <attr name="bar" />
+
+    <public type="style" name="Theme" id="0x7f020000" />
+    <style name="Theme" parent="com.android.lib_one:style/Theme">
+      <item name="foo">?com.android.lib_one:attr/attr2</item>
+      <item name="bar">@com.android.lib_one:string/foo</item>
+    </style>
+
+    <public type="string" name="foo_one" id="0x7f030000" />
+    <string name="foo_one">@com.android.lib_one:string/foo</string>
+
+    <public type="string" name="foo_two" id="0x7f030001" />
+    <string name="foo_two">@com.android.lib_two:string/foo</string>
+</resources>
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 8f7787b..138a5ef 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -7,7 +7,7 @@
 # Enables fine-grained GLES error checking
 # If set to true, every GLES call is wrapped & error checked
 # Has moderate overhead
-HWUI_ENABLE_OPENGL_VALIDATION := false
+HWUI_ENABLE_OPENGL_VALIDATION := true
 
 hwui_src_files := \
     hwui/Bitmap.cpp \
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 5e4a7f7..3853356 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -104,15 +104,15 @@
     }
 }
 
-bool DisplayList::prepareListAndChildren(TreeInfo& info, bool functorsNeedLayer,
-        std::function<void(RenderNode*, TreeInfo&, bool)> childFn) {
+bool DisplayList::prepareListAndChildren(TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
+        std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) {
     info.prepareTextures = info.canvasContext.pinImages(bitmapResources);
 
     for (auto&& op : children) {
         RenderNode* childNode = op->renderNode;
         info.damageAccumulator->pushTransform(&op->localMatrix);
         bool childFunctorsNeedLayer = functorsNeedLayer; // TODO! || op->mRecordedWithPotentialStencilClip;
-        childFn(childNode, info, childFunctorsNeedLayer);
+        childFn(childNode, observer, info, childFunctorsNeedLayer);
         info.damageAccumulator->popTransform();
     }
 
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index cab092f..ef0fd31 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -125,8 +125,8 @@
 
     virtual void syncContents();
     virtual void updateChildren(std::function<void(RenderNode*)> updateFn);
-    virtual bool prepareListAndChildren(TreeInfo& info, bool functorsNeedLayer,
-            std::function<void(RenderNode*, TreeInfo&, bool)> childFn);
+    virtual bool prepareListAndChildren(TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
+            std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn);
 
 protected:
     // allocator into which all ops and LsaVector arrays allocated
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index a5443d9..7d8f046 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -22,6 +22,7 @@
 #include "OpDumper.h"
 #include "RecordedOp.h"
 #include "TreeInfo.h"
+#include "utils/FatVector.h"
 #include "utils/MathUtils.h"
 #include "utils/StringUtils.h"
 #include "utils/TraceUtils.h"
@@ -39,6 +40,20 @@
 namespace android {
 namespace uirenderer {
 
+// Used for tree mutations that are purely destructive.
+// Generic tree mutations should use MarkAndSweepObserver instead
+class ImmediateRemoved : public TreeObserver {
+public:
+    explicit ImmediateRemoved(TreeInfo* info) : mTreeInfo(info) {}
+
+    void onMaybeRemovedFromTree(RenderNode* node) override {
+        node->onRemovedFromTree(mTreeInfo);
+    }
+
+private:
+    TreeInfo* mTreeInfo;
+};
+
 RenderNode::RenderNode()
         : mDirtyPropertyFields(0)
         , mNeedsDisplayListSync(false)
@@ -49,20 +64,17 @@
 }
 
 RenderNode::~RenderNode() {
-    deleteDisplayList(nullptr);
+    ImmediateRemoved observer(nullptr);
+    deleteDisplayList(observer);
     delete mStagingDisplayList;
     LOG_ALWAYS_FATAL_IF(hasLayer(), "layer missed detachment!");
 }
 
-void RenderNode::setStagingDisplayList(DisplayList* displayList, TreeObserver* observer) {
+void RenderNode::setStagingDisplayList(DisplayList* displayList) {
+    mValid = (displayList != nullptr);
     mNeedsDisplayListSync = true;
     delete mStagingDisplayList;
     mStagingDisplayList = displayList;
-    // If mParentCount == 0 we are the sole reference to this RenderNode,
-    // so immediately free the old display list
-    if (!mParentCount && !mStagingDisplayList) {
-        deleteDisplayList(observer);
-    }
 }
 
 /**
@@ -187,12 +199,13 @@
 void RenderNode::prepareTree(TreeInfo& info) {
     ATRACE_CALL();
     LOG_ALWAYS_FATAL_IF(!info.damageAccumulator, "DamageAccumulator missing");
+    MarkAndSweepRemoved observer(&info);
 
     // The OpenGL renderer reserves the stencil buffer for overdraw debugging.  Functors
     // will need to be drawn in a layer.
     bool functorsNeedLayer = Properties::debugOverdraw && !Properties::isSkiaEnabled();
 
-    prepareTreeImpl(info, functorsNeedLayer);
+    prepareTreeImpl(observer, info, functorsNeedLayer);
 }
 
 void RenderNode::addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
@@ -283,7 +296,7 @@
  * While traversing down the tree, functorsNeedLayer flag is set to true if anything that uses the
  * stencil buffer may be needed. Views that use a functor to draw will be forced onto a layer.
  */
-void RenderNode::prepareTreeImpl(TreeInfo& info, bool functorsNeedLayer) {
+void RenderNode::prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer) {
     info.damageAccumulator->pushTransform(this);
 
     if (info.mode == TreeInfo::MODE_FULL) {
@@ -309,14 +322,14 @@
 
     prepareLayer(info, animatorDirtyMask);
     if (info.mode == TreeInfo::MODE_FULL) {
-        pushStagingDisplayListChanges(info);
+        pushStagingDisplayListChanges(observer, info);
     }
 
     if (mDisplayList) {
         info.out.hasFunctors |= mDisplayList->hasFunctor();
-        bool isDirty = mDisplayList->prepareListAndChildren(info, childFunctorsNeedLayer,
-                [](RenderNode* child, TreeInfo& info, bool functorsNeedLayer) {
-            child->prepareTreeImpl(info, functorsNeedLayer);
+        bool isDirty = mDisplayList->prepareListAndChildren(observer, info, childFunctorsNeedLayer,
+                [](RenderNode* child, TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer) {
+            child->prepareTreeImpl(observer, info, functorsNeedLayer);
         });
         if (isDirty) {
             damageSelf(info);
@@ -353,7 +366,7 @@
     }
 }
 
-void RenderNode::syncDisplayList(TreeInfo* info) {
+void RenderNode::syncDisplayList(TreeObserver& observer, TreeInfo* info) {
     // Make sure we inc first so that we don't fluctuate between 0 and 1,
     // which would thrash the layer cache
     if (mStagingDisplayList) {
@@ -361,7 +374,7 @@
             child->incParentRefCount();
         });
     }
-    deleteDisplayList(info ? info->observer : nullptr, info);
+    deleteDisplayList(observer, info);
     mDisplayList = mStagingDisplayList;
     mStagingDisplayList = nullptr;
     if (mDisplayList) {
@@ -369,20 +382,20 @@
     }
 }
 
-void RenderNode::pushStagingDisplayListChanges(TreeInfo& info) {
+void RenderNode::pushStagingDisplayListChanges(TreeObserver& observer, TreeInfo& info) {
     if (mNeedsDisplayListSync) {
         mNeedsDisplayListSync = false;
         // Damage with the old display list first then the new one to catch any
         // changes in isRenderable or, in the future, bounds
         damageSelf(info);
-        syncDisplayList(&info);
+        syncDisplayList(observer, &info);
         damageSelf(info);
     }
 }
 
-void RenderNode::deleteDisplayList(TreeObserver* observer, TreeInfo* info) {
+void RenderNode::deleteDisplayList(TreeObserver& observer, TreeInfo* info) {
     if (mDisplayList) {
-        mDisplayList->updateChildren([observer, info](RenderNode* child) {
+        mDisplayList->updateChildren([&observer, info](RenderNode* child) {
             child->decParentRefCount(observer, info);
         });
         if (!mDisplayList->reuseDisplayList(this, info ? &info->canvasContext : nullptr)) {
@@ -392,38 +405,53 @@
     mDisplayList = nullptr;
 }
 
-void RenderNode::destroyHardwareResources(TreeObserver* observer, TreeInfo* info) {
+void RenderNode::destroyHardwareResources(TreeInfo* info) {
+    ImmediateRemoved observer(info);
+    destroyHardwareResourcesImpl(observer, info);
+}
+
+void RenderNode::destroyHardwareResourcesImpl(TreeObserver& observer, TreeInfo* info) {
     if (hasLayer()) {
         renderthread::CanvasContext::destroyLayer(this);
     }
     if (mDisplayList) {
-        mDisplayList->updateChildren([observer, info](RenderNode* child) {
-            child->destroyHardwareResources(observer, info);
+        mDisplayList->updateChildren([&observer, info](RenderNode* child) {
+            child->destroyHardwareResourcesImpl(observer, info);
         });
-        if (mNeedsDisplayListSync) {
-            // Next prepare tree we are going to push a new display list, so we can
-            // drop our current one now
-            deleteDisplayList(observer, info);
+        setStagingDisplayList(nullptr);
+        deleteDisplayList(observer, info);
+    }
+}
+
+void RenderNode::destroyLayers() {
+    if (hasLayer()) {
+        renderthread::CanvasContext::destroyLayer(this);
+    }
+    if (mDisplayList) {
+        mDisplayList->updateChildren([](RenderNode* child) {
+            child->destroyLayers();
+        });
+    }
+}
+
+void RenderNode::decParentRefCount(TreeObserver& observer, TreeInfo* info) {
+    LOG_ALWAYS_FATAL_IF(!mParentCount, "already 0!");
+    mParentCount--;
+    if (!mParentCount) {
+        observer.onMaybeRemovedFromTree(this);
+        if (CC_UNLIKELY(mPositionListener.get())) {
+            mPositionListener->onPositionLost(*this, info);
         }
     }
 }
 
-void RenderNode::decParentRefCount(TreeObserver* observer, TreeInfo* info) {
-    LOG_ALWAYS_FATAL_IF(!mParentCount, "already 0!");
-    mParentCount--;
-    if (!mParentCount) {
-        if (observer) {
-            observer->onMaybeRemovedFromTree(this);
-        }
-        if (CC_UNLIKELY(mPositionListener.get())) {
-            mPositionListener->onPositionLost(*this, info);
-        }
-        // If a child of ours is being attached to our parent then this will incorrectly
-        // destroy its hardware resources. However, this situation is highly unlikely
-        // and the failure is "just" that the layer is re-created, so this should
-        // be safe enough
-        destroyHardwareResources(observer, info);
-    }
+void RenderNode::onRemovedFromTree(TreeInfo* info) {
+    destroyHardwareResources(info);
+}
+
+void RenderNode::clearRoot() {
+    ImmediateRemoved observer(nullptr);
+    decParentRefCount(observer);
 }
 
 /**
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index b8964f0..14a664c 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -34,6 +34,7 @@
 #include "RenderProperties.h"
 #include "pipeline/skia/SkiaDisplayList.h"
 #include "pipeline/skia/SkiaLayer.h"
+#include "utils/FatVector.h"
 
 #include <vector>
 
@@ -101,7 +102,7 @@
         kReplayFlag_ClipChildren = 0x1
     };
 
-    ANDROID_API void setStagingDisplayList(DisplayList* newData, TreeObserver* observer);
+    ANDROID_API void setStagingDisplayList(DisplayList* newData);
 
     void computeOrdering();
 
@@ -164,6 +165,10 @@
         return mStagingProperties;
     }
 
+    bool isValid() {
+        return mValid;
+    }
+
     int getWidth() const {
         return properties().getWidth();
     }
@@ -173,7 +178,8 @@
     }
 
     ANDROID_API virtual void prepareTree(TreeInfo& info);
-    void destroyHardwareResources(TreeObserver* observer, TreeInfo* info = nullptr);
+    void destroyHardwareResources(TreeInfo* info = nullptr);
+    void destroyLayers();
 
     // UI thread only!
     ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
@@ -232,24 +238,35 @@
         return mParentCount;
     }
 
+    void onRemovedFromTree(TreeInfo* info);
+
+    // Called by CanvasContext to promote a RenderNode to be a root node
+    void makeRoot() {
+        incParentRefCount();
+    }
+
+    // Called by CanvasContext when it drops a RenderNode from being a root node
+    void clearRoot();
+
 private:
     void computeOrderingImpl(RenderNodeOp* opState,
             std::vector<RenderNodeOp*>* compositedChildrenOfProjectionSurface,
             const mat4* transformFromProjectionSurface);
 
     void syncProperties();
-    void syncDisplayList(TreeInfo* info);
+    void syncDisplayList(TreeObserver& observer, TreeInfo* info);
 
-    void prepareTreeImpl(TreeInfo& info, bool functorsNeedLayer);
+    void prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer);
     void pushStagingPropertiesChanges(TreeInfo& info);
-    void pushStagingDisplayListChanges(TreeInfo& info);
+    void pushStagingDisplayListChanges(TreeObserver& observer, TreeInfo& info);
     void prepareLayer(TreeInfo& info, uint32_t dirtyMask);
     void pushLayerUpdate(TreeInfo& info);
-    void deleteDisplayList(TreeObserver* observer, TreeInfo* info = nullptr);
+    void deleteDisplayList(TreeObserver& observer, TreeInfo* info = nullptr);
+    void destroyHardwareResourcesImpl(TreeObserver& observer, TreeInfo* info = nullptr);
     void damageSelf(TreeInfo& info);
 
     void incParentRefCount() { mParentCount++; }
-    void decParentRefCount(TreeObserver* observer, TreeInfo* info = nullptr);
+    void decParentRefCount(TreeObserver& observer, TreeInfo* info = nullptr);
     void output(std::ostream& output, uint32_t level);
 
     String8 mName;
@@ -259,6 +276,10 @@
     RenderProperties mProperties;
     RenderProperties mStagingProperties;
 
+    // Owned by UI. Set when DL is set, cleared when DL cleared or when node detached
+    // (likely by parent re-record/removal)
+    bool mValid = false;
+
     bool mNeedsDisplayListSync;
     // WARNING: Do not delete this directly, you must go through deleteDisplayList()!
     DisplayList* mDisplayList;
@@ -361,5 +382,28 @@
     std::unique_ptr<skiapipeline::SkiaLayer> mSkiaLayer;
 }; // class RenderNode
 
+class MarkAndSweepRemoved : public TreeObserver {
+PREVENT_COPY_AND_ASSIGN(MarkAndSweepRemoved);
+
+public:
+    explicit MarkAndSweepRemoved(TreeInfo* info) : mTreeInfo(info) {}
+
+    void onMaybeRemovedFromTree(RenderNode* node) override {
+        mMarked.emplace_back(node);
+    }
+
+    ~MarkAndSweepRemoved() {
+        for (auto& node : mMarked) {
+            if (!node->hasParents()) {
+                node->onRemovedFromTree(mTreeInfo);
+            }
+        }
+    }
+
+private:
+    FatVector<sp<RenderNode>, 10> mMarked;
+    TreeInfo* mTreeInfo;
+};
+
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 749efdd..c6fbe2b 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -47,9 +47,9 @@
     // Due to the unordered nature of tree pushes, once prepareTree
     // is finished it is possible that the node was "resurrected" and has
     // a non-zero parent count.
-    virtual void onMaybeRemovedFromTree(RenderNode* node) {}
+    virtual void onMaybeRemovedFromTree(RenderNode* node) = 0;
 protected:
-    ~TreeObserver() {}
+    virtual ~TreeObserver() {}
 };
 
 // This would be a struct, but we want to PREVENT_COPY_AND_ASSIGN
@@ -91,10 +91,6 @@
     LayerUpdateQueue* layerUpdateQueue = nullptr;
     ErrorHandler* errorHandler = nullptr;
 
-    // Optional, may be nullptr. Used to allow things to observe interesting
-    // tree state changes
-    TreeObserver* observer = nullptr;
-
     int32_t windowInsetLeft = 0;
     int32_t windowInsetTop = 0;
     bool updateWindowPositions = false;
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index 9db8cd3..36d02ecb 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -51,8 +51,9 @@
     }
 }
 
-bool SkiaDisplayList::prepareListAndChildren(TreeInfo& info, bool functorsNeedLayer,
-        std::function<void(RenderNode*, TreeInfo&, bool)> childFn) {
+bool SkiaDisplayList::prepareListAndChildren(TreeObserver& observer, TreeInfo& info,
+        bool functorsNeedLayer,
+        std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) {
     // If the prepare tree is triggered by the UI thread and no previous call to
     // pinImages has failed then we must pin all mutable images in the GPU cache
     // until the next UI thread draw.
@@ -74,7 +75,7 @@
         info.damageAccumulator->pushTransform(&mat4);
         // TODO: a layer is needed if the canvas is rotated or has a non-rect clip
         info.hasBackwardProjectedNodes = false;
-        childFn(childNode, info, functorsNeedLayer);
+        childFn(childNode, observer, info, functorsNeedLayer);
         hasBackwardProjectedNodesSubtree |= info.hasBackwardProjectedNodes;
         info.damageAccumulator->popTransform();
     }
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index ff86fd1..2a01330 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -113,8 +113,8 @@
      *       to subclass from DisplayList
      */
 
-    bool prepareListAndChildren(TreeInfo& info, bool functorsNeedLayer,
-            std::function<void(RenderNode*, TreeInfo&, bool)> childFn) override;
+    bool prepareListAndChildren(TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
+            std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) override;
 
     /**
      *  Calls the provided function once for each child of this DisplayList
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 1b3bf96..a53e5e0 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -146,21 +146,38 @@
         , mProfiler(mFrames)
         , mContentDrawBounds(0, 0, 0, 0)
         , mRenderPipeline(std::move(renderPipeline)) {
+    rootRenderNode->makeRoot();
     mRenderNodes.emplace_back(rootRenderNode);
     mRenderThread.renderState().registerCanvasContext(this);
     mProfiler.setDensity(mRenderThread.mainDisplayInfo().density);
 }
 
 CanvasContext::~CanvasContext() {
-    destroy(nullptr);
+    destroy();
     mRenderThread.renderState().unregisterCanvasContext(this);
+    for (auto& node : mRenderNodes) {
+        node->clearRoot();
+    }
+    mRenderNodes.clear();
 }
 
-void CanvasContext::destroy(TreeObserver* observer) {
+void CanvasContext::addRenderNode(RenderNode* node, bool placeFront) {
+    int pos = placeFront ? 0 : static_cast<int>(mRenderNodes.size());
+    node->makeRoot();
+    mRenderNodes.emplace(mRenderNodes.begin() + pos, node);
+}
+
+void CanvasContext::removeRenderNode(RenderNode* node) {
+    node->clearRoot();
+    mRenderNodes.erase(std::remove(mRenderNodes.begin(), mRenderNodes.end(), node),
+            mRenderNodes.end());
+}
+
+void CanvasContext::destroy() {
     stopDrawing();
     setSurface(nullptr);
-    freePrefetchedLayers(observer);
-    destroyHardwareResources(observer);
+    freePrefetchedLayers();
+    destroyHardwareResources();
     mAnimationContext->destroy();
 }
 
@@ -320,7 +337,7 @@
     mAnimationContext->runRemainingAnimations(info);
     GL_CHECKPOINT(MODERATE);
 
-    freePrefetchedLayers(info.observer);
+    freePrefetchedLayers();
     GL_CHECKPOINT(MODERATE);
 
     mIsDirty = true;
@@ -504,19 +521,19 @@
     }
 }
 
-void CanvasContext::freePrefetchedLayers(TreeObserver* observer) {
+void CanvasContext::freePrefetchedLayers() {
     if (mPrefetchedLayers.size()) {
         for (auto& node : mPrefetchedLayers) {
             ALOGW("Incorrectly called buildLayer on View: %s, destroying layer...",
                     node->getName());
-            node->destroyHardwareResources(observer);
-            node->decStrong(observer);
+            node->destroyLayers();
+            node->decStrong(nullptr);
         }
         mPrefetchedLayers.clear();
     }
 }
 
-void CanvasContext::buildLayer(RenderNode* node, TreeObserver* observer) {
+void CanvasContext::buildLayer(RenderNode* node) {
     ATRACE_CALL();
     if (!mRenderPipeline->isContextReady()) return;
 
@@ -525,7 +542,6 @@
 
     TreeInfo info(TreeInfo::MODE_FULL, *this);
     info.damageAccumulator = &mDamageAccumulator;
-    info.observer = observer;
     info.layerUpdateQueue = &mLayerUpdateQueue;
     info.runAnimations = false;
     node->prepareTree(info);
@@ -545,12 +561,12 @@
     return mRenderPipeline->copyLayerInto(layer, bitmap);
 }
 
-void CanvasContext::destroyHardwareResources(TreeObserver* observer) {
+void CanvasContext::destroyHardwareResources() {
     stopDrawing();
     if (mRenderPipeline->isContextReady()) {
-        freePrefetchedLayers(observer);
+        freePrefetchedLayers();
         for (const sp<RenderNode>& node : mRenderNodes) {
-            node->destroyHardwareResources(observer);
+            node->destroyHardwareResources();
         }
         mRenderPipeline->onDestroyHardwareResources();
     }
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 0174b86..aa01caa 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -132,17 +132,17 @@
     void prepareTree(TreeInfo& info, int64_t* uiFrameInfo,
             int64_t syncQueued, RenderNode* target);
     void draw();
-    void destroy(TreeObserver* observer);
+    void destroy();
 
     // IFrameCallback, Choreographer-driven frame callback entry point
     virtual void doFrame() override;
     void prepareAndDraw(RenderNode* node);
 
-    void buildLayer(RenderNode* node, TreeObserver* observer);
+    void buildLayer(RenderNode* node);
     bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
     void markLayerInUse(RenderNode* node);
 
-    void destroyHardwareResources(TreeObserver* observer);
+    void destroyHardwareResources();
     static void trimMemory(RenderThread& thread, int level);
 
     DeferredLayerUpdater* createTextureLayer();
@@ -160,15 +160,8 @@
 
     void serializeDisplayListTree();
 
-    void addRenderNode(RenderNode* node, bool placeFront) {
-        int pos = placeFront ? 0 : static_cast<int>(mRenderNodes.size());
-        mRenderNodes.emplace(mRenderNodes.begin() + pos, node);
-    }
-
-    void removeRenderNode(RenderNode* node) {
-        mRenderNodes.erase(std::remove(mRenderNodes.begin(), mRenderNodes.end(), node),
-                mRenderNodes.end());
-    }
+    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);
@@ -213,7 +206,7 @@
 
     void setSurface(Surface* window);
 
-    void freePrefetchedLayers(TreeObserver* observer);
+    void freePrefetchedLayers();
 
     bool isSwapChainStuffed();
 
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 4ff54a5..7d641d3 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -65,12 +65,11 @@
     }
 }
 
-int DrawFrameTask::drawFrame(TreeObserver* observer) {
+int DrawFrameTask::drawFrame() {
     LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
 
     mSyncResult = SyncResult::OK;
     mSyncQueued = systemTime(CLOCK_MONOTONIC);
-    mObserver = observer;
     postAndWait();
 
     return mSyncResult;
@@ -89,7 +88,6 @@
     bool canDrawThisFrame;
     {
         TreeInfo info(TreeInfo::MODE_FULL, *mContext);
-        info.observer = mObserver;
         canUnblockUiThread = syncFrameState(info);
         canDrawThisFrame = info.out.canDrawThisFrame;
     }
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index c02d376..fb48062 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -65,7 +65,7 @@
     void pushLayerUpdate(DeferredLayerUpdater* layer);
     void removeLayerUpdate(DeferredLayerUpdater* layer);
 
-    int drawFrame(TreeObserver* observer);
+    int drawFrame();
 
     int64_t* frameInfo() { return mFrameInfo; }
 
@@ -90,7 +90,6 @@
 
     int mSyncResult;
     int64_t mSyncQueued;
-    TreeObserver* mObserver;
 
     int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE];
 };
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 022e871..fb79272 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -230,19 +230,18 @@
     return mDrawFrameTask.frameInfo();
 }
 
-int RenderProxy::syncAndDrawFrame(TreeObserver* observer) {
-    return mDrawFrameTask.drawFrame(observer);
+int RenderProxy::syncAndDrawFrame() {
+    return mDrawFrameTask.drawFrame();
 }
 
-CREATE_BRIDGE2(destroy, CanvasContext* context, TreeObserver* observer) {
-    args->context->destroy(args->observer);
+CREATE_BRIDGE1(destroy, CanvasContext* context) {
+    args->context->destroy();
     return nullptr;
 }
 
-void RenderProxy::destroy(TreeObserver* observer) {
+void RenderProxy::destroy() {
     SETUP_TASK(destroy);
     args->context = mContext;
-    args->observer = observer;
     // destroyCanvasAndSurface() needs a fence as when it returns the
     // underlying BufferQueue is going to be released from under
     // the render thread.
@@ -282,16 +281,15 @@
     return layer;
 }
 
-CREATE_BRIDGE3(buildLayer, CanvasContext* context, RenderNode* node, TreeObserver* observer) {
-    args->context->buildLayer(args->node, args->observer);
+CREATE_BRIDGE2(buildLayer, CanvasContext* context, RenderNode* node) {
+    args->context->buildLayer(args->node);
     return nullptr;
 }
 
-void RenderProxy::buildLayer(RenderNode* node, TreeObserver* observer) {
+void RenderProxy::buildLayer(RenderNode* node) {
     SETUP_TASK(buildLayer);
     args->context = mContext;
     args->node = node;
-    args->observer = observer;
     postAndWait(task);
 }
 
@@ -328,15 +326,14 @@
     postAndWait(task);
 }
 
-CREATE_BRIDGE2(destroyHardwareResources, CanvasContext* context, TreeObserver* observer) {
-    args->context->destroyHardwareResources(args->observer);
+CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) {
+    args->context->destroyHardwareResources();
     return nullptr;
 }
 
-void RenderProxy::destroyHardwareResources(TreeObserver* observer) {
+void RenderProxy::destroyHardwareResources() {
     SETUP_TASK(destroyHardwareResources);
     args->context = mContext;
-    args->observer = observer;
     postAndWait(task);
 }
 
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 44a5a14..1629090 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -44,7 +44,6 @@
 class DisplayList;
 class Layer;
 class Rect;
-class TreeObserver;
 
 namespace renderthread {
 
@@ -87,19 +86,19 @@
     ANDROID_API void setLightCenter(const Vector3& lightCenter);
     ANDROID_API void setOpaque(bool opaque);
     ANDROID_API int64_t* frameInfo();
-    ANDROID_API int syncAndDrawFrame(TreeObserver* observer);
-    ANDROID_API void destroy(TreeObserver* observer);
+    ANDROID_API int syncAndDrawFrame();
+    ANDROID_API void destroy();
 
     ANDROID_API static void invokeFunctor(Functor* functor, bool waitForCompletion);
 
     ANDROID_API DeferredLayerUpdater* createTextureLayer();
-    ANDROID_API void buildLayer(RenderNode* node, TreeObserver* observer);
+    ANDROID_API void buildLayer(RenderNode* node);
     ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap);
     ANDROID_API void pushLayerUpdate(DeferredLayerUpdater* layer);
     ANDROID_API void cancelLayerUpdate(DeferredLayerUpdater* layer);
     ANDROID_API void detachSurfaceTexture(DeferredLayerUpdater* layer);
 
-    ANDROID_API void destroyHardwareResources(TreeObserver* observer);
+    ANDROID_API void destroyHardwareResources();
     ANDROID_API static void trimMemory(int level);
     ANDROID_API static void overrideProperty(const char* name, const char* value);
 
diff --git a/libs/hwui/tests/common/TestListViewSceneBase.cpp b/libs/hwui/tests/common/TestListViewSceneBase.cpp
index 6d2e8599..38c4848 100644
--- a/libs/hwui/tests/common/TestListViewSceneBase.cpp
+++ b/libs/hwui/tests/common/TestListViewSceneBase.cpp
@@ -69,7 +69,7 @@
         // draw it to parent DisplayList
         canvas->drawRenderNode(mListItems[ci].get());
     }
-    mListView->setStagingDisplayList(canvas->finishRecording(), nullptr);
+    mListView->setStagingDisplayList(canvas->finishRecording());
 }
 
 } // namespace test
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 8b287de..16bc6f7 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -156,6 +156,11 @@
         int* mSignal;
     };
 
+    class MockTreeObserver : public TreeObserver {
+    public:
+        virtual void onMaybeRemovedFromTree(RenderNode* node) {}
+    };
+
     static bool matricesAreApproxEqual(const Matrix4& a, const Matrix4& b) {
         for (int i = 0; i < 16; i++) {
             if (!MathUtils::areEqual(a[i], b[i])) {
@@ -215,7 +220,7 @@
             std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(props.getWidth(),
                     props.getHeight()));
             setup(props, *canvas.get());
-            node->setStagingDisplayList(canvas->finishRecording(), nullptr);
+            node->setStagingDisplayList(canvas->finishRecording());
         }
         node->setPropertyFieldsDirty(0xFFFFFFFF);
         return node;
@@ -236,7 +241,7 @@
         if (setup) {
             RecordingCanvasType canvas(props.getWidth(), props.getHeight());
             setup(props, canvas);
-            node->setStagingDisplayList(canvas.finishRecording(), nullptr);
+            node->setStagingDisplayList(canvas.finishRecording());
         }
         node->setPropertyFieldsDirty(0xFFFFFFFF);
         return node;
@@ -247,7 +252,7 @@
        std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(
             node.stagingProperties().getWidth(), node.stagingProperties().getHeight()));
        contentCallback(*canvas.get());
-       node.setStagingDisplayList(canvas->finishRecording(), nullptr);
+       node.setStagingDisplayList(canvas->finishRecording());
     }
 
     static sp<RenderNode> createSkiaNode(int left, int top, int right, int bottom,
@@ -265,14 +270,14 @@
         RenderProperties& props = node->mutateStagingProperties();
         props.setLeftTopRightBottom(left, top, right, bottom);
         if (displayList) {
-            node->setStagingDisplayList(displayList, nullptr);
+            node->setStagingDisplayList(displayList);
         }
         if (setup) {
             std::unique_ptr<skiapipeline::SkiaRecordingCanvas> canvas(
                 new skiapipeline::SkiaRecordingCanvas(nullptr,
                 props.getWidth(), props.getHeight()));
             setup(props, *canvas.get());
-            node->setStagingDisplayList(canvas->finishRecording(), nullptr);
+            node->setStagingDisplayList(canvas->finishRecording());
         }
         node->setPropertyFieldsDirty(0xFFFFFFFF);
         TestUtils::syncHierarchyPropertiesAndDisplayList(node);
@@ -350,8 +355,9 @@
 
 private:
     static void syncHierarchyPropertiesAndDisplayListImpl(RenderNode* node) {
+        MarkAndSweepRemoved observer(nullptr);
         node->syncProperties();
-        node->syncDisplayList(nullptr);
+        node->syncDisplayList(observer, nullptr);
         auto displayList = node->getDisplayList();
         if (displayList) {
             for (auto&& childOp : displayList->getChildren()) {
diff --git a/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp b/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
index c0d9450..5b685bb 100644
--- a/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
@@ -60,6 +60,6 @@
                     0, 100 * (i + 2), minikin::kBidi_Force_LTR, paint, nullptr);
         }
 
-        container->setStagingDisplayList(canvas->finishRecording(), nullptr);
+        container->setStagingDisplayList(canvas->finishRecording());
     }
 };
diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
index 396e896..f8d6397 100644
--- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -151,7 +151,7 @@
         testContext.waitForVsync();
         nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
         UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
-        proxy->syncAndDrawFrame(nullptr);
+        proxy->syncAndDrawFrame();
     }
 
     proxy->resetProfileInfo();
@@ -167,7 +167,7 @@
             ATRACE_NAME("UI-Draw Frame");
             UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
             scene->doFrame(i);
-            proxy->syncAndDrawFrame(nullptr);
+            proxy->syncAndDrawFrame();
         }
         if (opts.reportFrametimeWeight) {
             proxy->fence();
diff --git a/libs/hwui/tests/unit/CanvasContextTests.cpp b/libs/hwui/tests/unit/CanvasContextTests.cpp
index 42ba3db..ef5ce0d 100644
--- a/libs/hwui/tests/unit/CanvasContextTests.cpp
+++ b/libs/hwui/tests/unit/CanvasContextTests.cpp
@@ -40,7 +40,7 @@
 
     ASSERT_FALSE(canvasContext->hasSurface());
 
-    canvasContext->destroy(nullptr);
+    canvasContext->destroy();
 }
 
 RENDERTHREAD_TEST(CanvasContext, invokeFunctor) {
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index 5a2791c..a391d1e 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -322,10 +322,14 @@
     }
 
     for (auto& node : nodes) {
+        EXPECT_TRUE(node->isValid());
         EXPECT_FALSE(node->nothingToDraw());
-        node->setStagingDisplayList(nullptr, nullptr);
-        node->destroyHardwareResources(nullptr);
+        node->setStagingDisplayList(nullptr);
+        EXPECT_FALSE(node->isValid());
+        EXPECT_FALSE(node->nothingToDraw());
+        node->destroyHardwareResources();
         EXPECT_TRUE(node->nothingToDraw());
+        EXPECT_FALSE(node->isValid());
     }
 
     {
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index 2f1eae3..f21b3f7 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -321,7 +321,6 @@
     TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
     DamageAccumulator damageAccumulator;
     info.damageAccumulator = &damageAccumulator;
-    info.observer = nullptr;
     parent->prepareTree(info);
 
     //parent(A)             -> (receiverBackground, child)
@@ -437,7 +436,6 @@
     TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
     DamageAccumulator damageAccumulator;
     info.damageAccumulator = &damageAccumulator;
-    info.observer = nullptr;
     parent->prepareTree(info);
 
     int drawCounter = 0;
@@ -527,7 +525,6 @@
     TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
     DamageAccumulator damageAccumulator;
     info.damageAccumulator = &damageAccumulator;
-    info.observer = nullptr;
     parent->prepareTree(info);
 
     std::unique_ptr<ProjectionChildScrollTestCanvas> canvas(new ProjectionChildScrollTestCanvas());
@@ -545,7 +542,6 @@
     TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
     DamageAccumulator damageAccumulator;
     info.damageAccumulator = &damageAccumulator;
-    info.observer = nullptr;
     renderNode->prepareTree(info);
 
     //create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection
diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp
index ab8e4e1..8af4bbe 100644
--- a/libs/hwui/tests/unit/RenderNodeTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeTests.cpp
@@ -66,6 +66,70 @@
     EXPECT_FALSE(parent->hasParents()) << "Root node shouldn't have any parents";
 }
 
+TEST(RenderNode, validity) {
+    auto child = TestUtils::createNode(0, 0, 200, 400,
+            [](RenderProperties& props, Canvas& canvas) {
+        canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
+    });
+    auto parent = TestUtils::createNode(0, 0, 200, 400,
+            [&child](RenderProperties& props, Canvas& canvas) {
+        canvas.drawRenderNode(child.get());
+    });
+
+    EXPECT_TRUE(child->isValid());
+    EXPECT_TRUE(parent->isValid());
+    EXPECT_TRUE(child->nothingToDraw());
+    EXPECT_TRUE(parent->nothingToDraw());
+
+    TestUtils::syncHierarchyPropertiesAndDisplayList(parent);
+
+    EXPECT_TRUE(child->isValid());
+    EXPECT_TRUE(parent->isValid());
+    EXPECT_FALSE(child->nothingToDraw());
+    EXPECT_FALSE(parent->nothingToDraw());
+
+    TestUtils::recordNode(*parent, [](Canvas& canvas) {
+        canvas.drawColor(Color::Amber_500, SkBlendMode::kSrcOver);
+    });
+
+    EXPECT_TRUE(child->isValid());
+    EXPECT_TRUE(parent->isValid());
+    EXPECT_FALSE(child->nothingToDraw());
+    EXPECT_FALSE(parent->nothingToDraw());
+
+    TestUtils::syncHierarchyPropertiesAndDisplayList(parent);
+
+    EXPECT_FALSE(child->isValid());
+    EXPECT_TRUE(parent->isValid());
+    EXPECT_TRUE(child->nothingToDraw());
+    EXPECT_FALSE(parent->nothingToDraw());
+
+    TestUtils::recordNode(*child, [](Canvas& canvas) {
+        canvas.drawColor(Color::Amber_500, SkBlendMode::kSrcOver);
+    });
+
+    EXPECT_TRUE(child->isValid());
+    EXPECT_TRUE(child->nothingToDraw());
+
+    TestUtils::recordNode(*parent, [&child](Canvas& canvas) {
+        canvas.drawRenderNode(child.get());
+    });
+
+    TestUtils::syncHierarchyPropertiesAndDisplayList(parent);
+
+    EXPECT_TRUE(child->isValid());
+    EXPECT_TRUE(parent->isValid());
+    EXPECT_FALSE(child->nothingToDraw());
+    EXPECT_FALSE(parent->nothingToDraw());
+
+    parent->destroyHardwareResources();
+
+    EXPECT_FALSE(child->isValid());
+    EXPECT_FALSE(parent->isValid());
+    EXPECT_TRUE(child->nothingToDraw());
+    EXPECT_TRUE(parent->nothingToDraw());
+}
+
 TEST(RenderNode, releasedCallback) {
     class DecRefOnReleased : public GlFunctorLifecycleListener {
     public:
@@ -112,7 +176,6 @@
     TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get());
     DamageAccumulator damageAccumulator;
     info.damageAccumulator = &damageAccumulator;
-    info.observer = nullptr;
 
     {
         auto nonNullDLNode = TestUtils::createNode(0, 0, 200, 400,
@@ -131,7 +194,7 @@
         nullDLNode->prepareTree(info);
     }
 
-    canvasContext->destroy(nullptr);
+    canvasContext->destroy();
 }
 
 RENDERTHREAD_TEST(RenderNode, prepareTree_HwLayer_AVD_enqueueDamage) {
@@ -151,7 +214,6 @@
     LayerUpdateQueue layerUpdateQueue;
     info.damageAccumulator = &damageAccumulator;
     info.layerUpdateQueue = &layerUpdateQueue;
-    info.observer = nullptr;
 
     // Put node on HW layer
     rootNode->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer);
@@ -165,5 +227,5 @@
     EXPECT_FALSE(info.layerUpdateQueue->entries().empty());
     EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode);
     EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage);
-    canvasContext->destroy(nullptr);
+    canvasContext->destroy();
 }
diff --git a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
index 8f6fc8b..be460bf 100644
--- a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
+++ b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp
@@ -126,7 +126,6 @@
     TreeInfo info(TreeInfo::MODE_FULL, *canvasContext.get());
     DamageAccumulator damageAccumulator;
     info.damageAccumulator = &damageAccumulator;
-    info.observer = nullptr;
 
     SkiaDisplayList skiaDL(SkRect::MakeWH(200, 200));
 
@@ -137,7 +136,9 @@
 
     ASSERT_FALSE(cleanVD.isDirty());
     ASSERT_FALSE(cleanVD.getPropertyChangeWillBeConsumed());
-    ASSERT_FALSE(skiaDL.prepareListAndChildren(info, false, [](RenderNode*, TreeInfo&, bool) {}));
+    TestUtils::MockTreeObserver observer;
+    ASSERT_FALSE(skiaDL.prepareListAndChildren(observer, info, false,
+            [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
     ASSERT_TRUE(cleanVD.getPropertyChangeWillBeConsumed());
 
     // prepare again this time adding a dirty VD
@@ -146,7 +147,8 @@
 
     ASSERT_TRUE(dirtyVD.isDirty());
     ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
-    ASSERT_TRUE(skiaDL.prepareListAndChildren(info, false, [](RenderNode*, TreeInfo&, bool) {}));
+    ASSERT_TRUE(skiaDL.prepareListAndChildren(observer, info, false,
+            [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
     ASSERT_TRUE(dirtyVD.getPropertyChangeWillBeConsumed());
 
     // prepare again this time adding a RenderNode and a callback
@@ -155,8 +157,8 @@
     SkCanvas dummyCanvas;
     skiaDL.mChildNodes.emplace_back(renderNode.get(), &dummyCanvas);
     bool hasRun = false;
-    ASSERT_TRUE(skiaDL.prepareListAndChildren(info, false,
-            [&hasRun, renderNode, infoPtr](RenderNode* n, TreeInfo& i, bool r) {
+    ASSERT_TRUE(skiaDL.prepareListAndChildren(observer, info, false,
+            [&hasRun, renderNode, infoPtr](RenderNode* n, TreeObserver& observer, TreeInfo& i, bool r) {
         hasRun = true;
         ASSERT_EQ(renderNode.get(), n);
         ASSERT_EQ(infoPtr, &i);
@@ -164,7 +166,7 @@
     }));
     ASSERT_TRUE(hasRun);
 
-    canvasContext->destroy(nullptr);
+    canvasContext->destroy();
 }
 
 TEST(SkiaDisplayList, updateChildren) {
diff --git a/libs/hwui/utils/TestWindowContext.cpp b/libs/hwui/utils/TestWindowContext.cpp
index 8b80d69..79fc864 100644
--- a/libs/hwui/utils/TestWindowContext.cpp
+++ b/libs/hwui/utils/TestWindowContext.cpp
@@ -98,8 +98,8 @@
     }
 
     void finishDrawing() {
-        mRootNode->setStagingDisplayList(mCanvas->finishRecording(), nullptr);
-        mProxy->syncAndDrawFrame(nullptr);
+        mRootNode->setStagingDisplayList(mCanvas->finishRecording());
+        mProxy->syncAndDrawFrame();
         // Surprisingly, calling mProxy->fence() here appears to make no difference to
         // the timings we record.
     }
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index dc8264a..391a905 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -306,12 +306,26 @@
      * until there are no glitches.
      * This tuning step should be done while playing silence.
      * This technique provides a compromise between latency and glitch rate.
+     *
+     * @deprecated Use {@link AudioTrack.Builder#setPerformanceMode(int)} with
+     * {@link AudioTrack#PERFORMANCE_MODE_LOW_LATENCY} to control performance.
      */
     public final static int FLAG_LOW_LATENCY = 0x1 << 8;
 
+    /**
+     * @hide
+     * Flag requesting a deep buffer path when creating an {@code AudioTrack}.
+     *
+     * A deep buffer path, if available, may consume less power and is
+     * suitable for media playback where latency is not a concern.
+     * Use {@link AudioTrack.Builder#setPerformanceMode(int)} with
+     * {@link AudioTrack#PERFORMANCE_MODE_POWER_SAVING} to enable.
+     */
+    public final static int FLAG_DEEP_BUFFER = 0x1 << 9;
+
     private final static int FLAG_ALL = FLAG_AUDIBILITY_ENFORCED | FLAG_SECURE | FLAG_SCO |
             FLAG_BEACON | FLAG_HW_AV_SYNC | FLAG_HW_HOTWORD | FLAG_BYPASS_INTERRUPTION_POLICY |
-            FLAG_BYPASS_MUTE | FLAG_LOW_LATENCY;
+            FLAG_BYPASS_MUTE | FLAG_LOW_LATENCY | FLAG_DEEP_BUFFER;
     private final static int FLAG_ALL_PUBLIC = FLAG_AUDIBILITY_ENFORCED |
             FLAG_HW_AV_SYNC | FLAG_LOW_LATENCY;
 
@@ -541,6 +555,8 @@
 
         /**
          * Sets the combination of flags.
+         *
+         * This is a bitwise OR with the existing flags.
          * @param flags a combination of {@link AudioAttributes#FLAG_AUDIBILITY_ENFORCED},
          *    {@link AudioAttributes#FLAG_HW_AV_SYNC}.
          * @return the same Builder instance.
@@ -553,6 +569,17 @@
 
         /**
          * @hide
+         * Replaces flags.
+         * @param flags any combination of {@link AudioAttributes#FLAG_ALL}.
+         * @return the same Builder instance.
+         */
+        public Builder replaceFlags(int flags) {
+            mFlags = flags & AudioAttributes.FLAG_ALL;
+            return this;
+        }
+
+        /**
+         * @hide
          * Adds a Bundle of data
          * @param bundle a non-null Bundle
          * @return the same builder instance
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index bcae71c..fa904cd 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -4074,7 +4074,9 @@
      * currently connected to the system and meeting the criteria specified in the
      * <code>flags</code> parameter.
      * @param flags A set of bitflags specifying the criteria to test.
-     * @see {@link GET_DEVICES_OUTPUTS}, {@link GET_DEVICES_INPUTS} and {@link GET_DEVICES_ALL}.
+     * @see #GET_DEVICES_OUTPUTS
+     * @see #GET_DEVICES_INPUTS
+     * @see #GET_DEVICES_ALL
      * @return A (possibly zero-length) array of AudioDeviceInfo objects.
      */
     public AudioDeviceInfo[] getDevices(int flags) {
@@ -4145,7 +4147,9 @@
      * parameter.
      * This is an internal function. The public API front is getDevices(int).
      * @param flags A set of bitflags specifying the criteria to test.
-     * @see {@link GET_DEVICES_OUTPUTS}, {@link GET_DEVICES_INPUTS} and {@link GET_DEVICES_ALL}.
+     * @see #GET_DEVICES_OUTPUTS
+     * @see #GET_DEVICES_INPUTS
+     * @see #GET_DEVICES_ALL
      * @return A (possibly zero-length) array of AudioDeviceInfo objects.
      * @hide
      */
@@ -4191,7 +4195,7 @@
      * Unregisters an {@link AudioDeviceCallback} object which has been previously registered
      * to receive notifications of changes to the set of connected audio devices.
      * @param callback The {@link AudioDeviceCallback} object that was previously registered
-     * with {@link AudioManager#registerAudioDeviceCallback) to be unregistered.
+     * with {@link AudioManager#registerAudioDeviceCallback} to be unregistered.
      */
     public void unregisterAudioDeviceCallback(AudioDeviceCallback callback) {
         synchronized (mDeviceCallbacks) {
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 031ac06..b23f5fd 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -214,6 +214,66 @@
      */
     public final static int WRITE_NON_BLOCKING = 1;
 
+    /** @hide */
+    @IntDef({
+        PERFORMANCE_MODE_NONE,
+        PERFORMANCE_MODE_LOW_LATENCY,
+        PERFORMANCE_MODE_POWER_SAVING
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PerformanceMode {}
+
+    /**
+     * Default performance mode for an {@link AudioTrack}.
+     */
+    public static final int PERFORMANCE_MODE_NONE = 0;
+
+    /**
+     * Low latency performance mode for an {@link AudioTrack}.
+     * If the device supports it, this mode
+     * enables a lower latency path through to the audio output sink.
+     * Effects may no longer work with such an {@code AudioTrack} and
+     * the sample rate must match that of the output sink.
+     * <p>
+     * Applications should be aware that low latency requires careful
+     * buffer management, with smaller chunks of audio data written by each
+     * {@code write()} call.
+     * <p>
+     * If this flag is used without specifying a {@code bufferSizeInBytes} then the
+     * {@code AudioTrack}'s actual buffer size may be too small.
+     * It is recommended that a fairly
+     * large buffer should be specified when the {@code AudioTrack} is created.
+     * Then the actual size can be reduced by calling
+     * {@link #setBufferSizeInFrames(int)}. The buffer size can be optimized
+     * by lowering it after each {@code write()} call until the audio glitches,
+     * which is detected by calling
+     * {@link #getUnderrunCount()}. Then the buffer size can be increased
+     * until there are no glitches.
+     * This tuning step should be done while playing silence.
+     * This technique provides a compromise between latency and glitch rate.
+     */
+    public static final int PERFORMANCE_MODE_LOW_LATENCY = 1;
+
+    /**
+     * Power saving performance mode for an {@link AudioTrack}.
+     * If the device supports it, this
+     * mode will enable a lower power path to the audio output sink.
+     * In addition, this lower power path typically will have
+     * deeper internal buffers and better underrun resistance,
+     * with a tradeoff of higher latency.
+     * <p>
+     * In this mode, applications should attempt to use a larger buffer size
+     * and deliver larger chunks of audio data per {@code write()} call.
+     * Use {@link #getBufferSizeInFrames()} to determine
+     * the actual buffer size of the {@code AudioTrack} as it may have increased
+     * to accommodate a deeper buffer.
+     */
+    public static final int PERFORMANCE_MODE_POWER_SAVING = 2;
+
+    // keep in sync with system/media/audio/include/system/audio-base.h
+    private static final int AUDIO_OUTPUT_FLAG_FAST = 0x4;
+    private static final int AUDIO_OUTPUT_FLAG_DEEP_BUFFER = 0x8;
+
     //--------------------------------------------------------------------------
     // Member variables
     //--------------------
@@ -648,6 +708,7 @@
         private int mBufferSizeInBytes;
         private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
         private int mMode = MODE_STREAM;
+        private int mPerformanceMode = PERFORMANCE_MODE_NONE;
 
         /**
          * Constructs a new Builder with the default values as described above.
@@ -752,6 +813,32 @@
         }
 
         /**
+         * Sets the {@link AudioTrack} performance mode.  This is an advisory request which
+         * may not be supported by the particular device, and the framework is free
+         * to ignore such request if it is incompatible with other requests or hardware.
+         *
+         * @param performanceMode one of
+         * {@link AudioTrack#PERFORMANCE_MODE_NONE},
+         * {@link AudioTrack#PERFORMANCE_MODE_LOW_LATENCY},
+         * or {@link AudioTrack#PERFORMANCE_MODE_POWER_SAVING}.
+         * @return the same Builder instance.
+         * @throws IllegalArgumentException if {@code performanceMode} is not valid.
+         */
+        public @NonNull Builder setPerformanceMode(@PerformanceMode int performanceMode) {
+            switch (performanceMode) {
+                case PERFORMANCE_MODE_NONE:
+                case PERFORMANCE_MODE_LOW_LATENCY:
+                case PERFORMANCE_MODE_POWER_SAVING:
+                    mPerformanceMode = performanceMode;
+                    break;
+                default:
+                    throw new IllegalArgumentException(
+                            "Invalid performance mode " + performanceMode);
+            }
+            return this;
+        }
+
+        /**
          * Builds an {@link AudioTrack} instance initialized with all the parameters set
          * on this <code>Builder</code>.
          * @return a new successfully initialized {@link AudioTrack} instance.
@@ -765,6 +852,25 @@
                         .setUsage(AudioAttributes.USAGE_MEDIA)
                         .build();
             }
+            switch (mPerformanceMode) {
+            case PERFORMANCE_MODE_LOW_LATENCY:
+                mAttributes = new AudioAttributes.Builder(mAttributes)
+                    .replaceFlags((mAttributes.getAllFlags()
+                            | AudioAttributes.FLAG_LOW_LATENCY)
+                            & ~AudioAttributes.FLAG_DEEP_BUFFER)
+                    .build();
+                break;
+            case PERFORMANCE_MODE_NONE:
+                break;
+            case PERFORMANCE_MODE_POWER_SAVING:
+                mAttributes = new AudioAttributes.Builder(mAttributes)
+                .replaceFlags((mAttributes.getAllFlags()
+                        | AudioAttributes.FLAG_DEEP_BUFFER)
+                        & ~AudioAttributes.FLAG_LOW_LATENCY)
+                .build();
+                break;
+            }
+
             if (mFormat == null) {
                 mFormat = new AudioFormat.Builder()
                         .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)
@@ -1278,6 +1384,27 @@
     }
 
     /**
+     * Returns the current performance mode of the {@link AudioTrack}.
+     *
+     * @return one of {@link AudioTrack#PERFORMANCE_MODE_NONE},
+     * {@link AudioTrack#PERFORMANCE_MODE_LOW_LATENCY},
+     * or {@link AudioTrack#PERFORMANCE_MODE_POWER_SAVING}.
+     * Use {@link AudioTrack.Builder#setPerformanceMode}
+     * in the {@link AudioTrack.Builder} to enable a performance mode.
+     * @throws IllegalStateException if track is not initialized.
+     */
+    public @PerformanceMode int getPerformanceMode() {
+        final int flags = native_get_flags();
+        if ((flags & AUDIO_OUTPUT_FLAG_FAST) != 0) {
+            return PERFORMANCE_MODE_LOW_LATENCY;
+        } else if ((flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) != 0) {
+            return PERFORMANCE_MODE_POWER_SAVING;
+        } else {
+            return PERFORMANCE_MODE_NONE;
+        }
+    }
+
+    /**
      *  Returns the output sample rate in Hz for the specified stream type.
      */
     static public int getNativeOutputSampleRate(int streamType) {
@@ -2855,6 +2982,8 @@
 
     private native final int native_get_underrun_count();
 
+    private native final int native_get_flags();
+
     // longArray must be a non-null array of length >= 2
     // [0] is assigned the frame position
     // [1] is assigned the time in CLOCK_MONOTONIC nanoseconds
diff --git a/media/java/android/media/BufferingParams.aidl b/media/java/android/media/BufferingParams.aidl
new file mode 100644
index 0000000..d156d44
--- /dev/null
+++ b/media/java/android/media/BufferingParams.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+parcelable BufferingParams;
diff --git a/media/java/android/media/BufferingParams.java b/media/java/android/media/BufferingParams.java
new file mode 100644
index 0000000..fdcd6ba
--- /dev/null
+++ b/media/java/android/media/BufferingParams.java
@@ -0,0 +1,459 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.annotation.IntDef;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Structure for source buffering management params.
+ *
+ * Used by {@link MediaPlayer#getDefaultBufferingParams()},
+ * {@link MediaPlayer#getBufferingParams()} and
+ * {@link MediaPlayer#setBufferingParams(BufferingParams)}
+ * to control source buffering behavior.
+ *
+ * <p>There are two stages of source buffering in {@link MediaPlayer}: initial buffering
+ * (when {@link MediaPlayer} is being prepared) and rebuffering (when {@link MediaPlayer}
+ * is playing back source). {@link BufferingParams} includes mode and corresponding
+ * watermarks for each stage of source buffering. The watermarks could be either size
+ * based (in milliseconds), or time based (in kilobytes) or both, depending on the mode.
+ *
+ * <p>There are 4 buffering modes: {@link #BUFFERING_MODE_NONE},
+ * {@link #BUFFERING_MODE_TIME_ONLY}, {@link #BUFFERING_MODE_SIZE_ONLY} and
+ * {@link #BUFFERING_MODE_TIME_THEN_SIZE}.
+ * {@link MediaPlayer} source component has default buffering modes which can be queried
+ * by calling {@link MediaPlayer#getDefaultBufferingParams()}.
+ * Users should always use those default modes or their downsized version when trying to
+ * change buffering params. For example, {@link #BUFFERING_MODE_TIME_THEN_SIZE} can be
+ * downsized to {@link #BUFFERING_MODE_NONE}, {@link #BUFFERING_MODE_TIME_ONLY} or
+ * {@link #BUFFERING_MODE_SIZE_ONLY}. But {@link #BUFFERING_MODE_TIME_ONLY} can not be
+ * downsized to {@link #BUFFERING_MODE_SIZE_ONLY}.
+ * <ul>
+ * <li><strong>initial buffering stage:</strong> has one watermark which is used when
+ * {@link MediaPlayer} is being prepared. When cached data amount exceeds this watermark,
+ * {@link MediaPlayer} is prepared.</li>
+ * <li><strong>rebuffering stage:</strong> has two watermarks, low and high, which are
+ * used when {@link MediaPlayer} is playing back content.
+ * <ul>
+ * <li> When cached data amount exceeds high watermark, {@link MediaPlayer} will pause
+ * buffering. Buffering will resume when cache runs below some limit which could be low
+ * watermark or some intermediate value decided by the source component.</li>
+ * <li> When cached data amount runs below low watermark, {@link MediaPlayer} will paused
+ * playback. Playback will resume when cached data amount exceeds high watermark
+ * or reaches end of stream.</li>
+ * </ul>
+ * </ul>
+ * <p>Users should use {@link Builder} to change {@link BufferingParams}.
+ */
+public final class BufferingParams implements Parcelable {
+    /**
+     * This mode indicates that source buffering is not supported.
+     */
+    public static final int BUFFERING_MODE_NONE = 0;
+    /**
+     * This mode indicates that only time based source buffering is supported. This means
+     * the watermark(s) are time based.
+     */
+    public static final int BUFFERING_MODE_TIME_ONLY = 1;
+    /**
+     * This mode indicates that only size based source buffering is supported. This means
+     * the watermark(s) are size based.
+     */
+    public static final int BUFFERING_MODE_SIZE_ONLY = 2;
+    /**
+     * This mode indicates that both time and size based source buffering are supported,
+     * and time based calculation precedes size based. Size based calculation will be used
+     * only when time information is not available from the source.
+     */
+    public static final int BUFFERING_MODE_TIME_THEN_SIZE = 3;
+
+    /** @hide */
+    @IntDef(
+        value = {
+                BUFFERING_MODE_NONE,
+                BUFFERING_MODE_TIME_ONLY,
+                BUFFERING_MODE_SIZE_ONLY,
+                BUFFERING_MODE_TIME_THEN_SIZE,
+        }
+    )
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface BufferingMode {}
+
+    private static final int BUFFERING_NO_WATERMARK = -1;
+
+    // params
+    private int mInitialBufferingMode = BUFFERING_MODE_NONE;
+    private int mRebufferingMode = BUFFERING_MODE_NONE;
+
+    private int mInitialWatermarkMs = BUFFERING_NO_WATERMARK;
+    private int mInitialWatermarkKB = BUFFERING_NO_WATERMARK;
+
+    private int mRebufferingWatermarkLowMs = BUFFERING_NO_WATERMARK;
+    private int mRebufferingWatermarkHighMs = BUFFERING_NO_WATERMARK;
+    private int mRebufferingWatermarkLowKB = BUFFERING_NO_WATERMARK;
+    private int mRebufferingWatermarkHighKB = BUFFERING_NO_WATERMARK;
+
+    private BufferingParams() {
+    }
+
+    /**
+     * Return the initial buffering mode used when {@link MediaPlayer} is being prepared.
+     * @return one of the values that can be set in {@link Builder#setInitialBufferingMode(int)}
+     */
+    public int getInitialBufferingMode() {
+        return mInitialBufferingMode;
+    }
+
+    /**
+     * Return the rebuffering mode used when {@link MediaPlayer} is playing back source.
+     * @return one of the values that can be set in {@link Builder#setRebufferingMode(int)}
+     */
+    public int getRebufferingMode() {
+        return mRebufferingMode;
+    }
+
+    /**
+     * Return the time based initial buffering watermark in milliseconds.
+     * It is meaningful only when initial buffering mode obatined from
+     * {@link #getInitialBufferingMode()} is time based.
+     * @return time based initial buffering watermark in milliseconds
+     */
+    public int getInitialBufferingWatermarkMs() {
+        return mInitialWatermarkMs;
+    }
+
+    /**
+     * Return the size based initial buffering watermark in kilobytes.
+     * It is meaningful only when initial buffering mode obatined from
+     * {@link #getInitialBufferingMode()} is size based.
+     * @return size based initial buffering watermark in kilobytes
+     */
+    public int getInitialBufferingWatermarkKB() {
+        return mInitialWatermarkKB;
+    }
+
+    /**
+     * Return the time based low watermark in milliseconds for rebuffering.
+     * It is meaningful only when rebuffering mode obatined from
+     * {@link #getRebufferingMode()} is time based.
+     * @return time based low watermark for rebuffering in milliseconds
+     */
+    public int getRebufferingWatermarkLowMs() {
+        return mRebufferingWatermarkLowMs;
+    }
+
+    /**
+     * Return the time based high watermark in milliseconds for rebuffering.
+     * It is meaningful only when rebuffering mode obatined from
+     * {@link #getRebufferingMode()} is time based.
+     * @return time based high watermark for rebuffering in milliseconds
+     */
+    public int getRebufferingWatermarkHighMs() {
+        return mRebufferingWatermarkHighMs;
+    }
+
+    /**
+     * Return the size based low watermark in kilobytes for rebuffering.
+     * It is meaningful only when rebuffering mode obatined from
+     * {@link #getRebufferingMode()} is size based.
+     * @return size based low watermark for rebuffering in kilobytes
+     */
+    public int getRebufferingWatermarkLowKB() {
+        return mRebufferingWatermarkLowKB;
+    }
+
+    /**
+     * Return the size based high watermark in kilobytes for rebuffering.
+     * It is meaningful only when rebuffering mode obatined from
+     * {@link #getRebufferingMode()} is size based.
+     * @return size based high watermark for rebuffering in kilobytes
+     */
+    public int getRebufferingWatermarkHighKB() {
+        return mRebufferingWatermarkHighKB;
+    }
+
+    /**
+     * Builder class for {@link BufferingParams} objects.
+     * <p> Here is an example where <code>Builder</code> is used to define the
+     * {@link BufferingParams} to be used by a {@link MediaPlayer} instance:
+     *
+     * <pre class="prettyprint">
+     * BufferingParams myParams = mediaplayer.getDefaultBufferingParams();
+     * myParams = new BufferingParams.Builder(myParams)
+     *             .setInitialBufferingWatermarkMs(10000)
+     *             .build();
+     * mediaplayer.setBufferingParams(myParams);
+     * </pre>
+     */
+    public static class Builder {
+        private int mInitialBufferingMode = BUFFERING_MODE_NONE;
+        private int mRebufferingMode = BUFFERING_MODE_NONE;
+
+        private int mInitialWatermarkMs = BUFFERING_NO_WATERMARK;
+        private int mInitialWatermarkKB = BUFFERING_NO_WATERMARK;
+
+        private int mRebufferingWatermarkLowMs = BUFFERING_NO_WATERMARK;
+        private int mRebufferingWatermarkHighMs = BUFFERING_NO_WATERMARK;
+        private int mRebufferingWatermarkLowKB = BUFFERING_NO_WATERMARK;
+        private int mRebufferingWatermarkHighKB = BUFFERING_NO_WATERMARK;
+
+        /**
+         * Constructs a new Builder with the defaults.
+         * By default, both initial buffering mode and rebuffering mode are
+         * {@link BufferingParams#BUFFERING_MODE_NONE}, and all watermarks are -1.
+         */
+        public Builder() {
+        }
+
+        /**
+         * Constructs a new Builder from a given {@link BufferingParams} instance
+         * @param bp the {@link BufferingParams} object whose data will be reused
+         * in the new Builder.
+         */
+        public Builder(BufferingParams bp) {
+            mInitialBufferingMode = bp.mInitialBufferingMode;
+            mRebufferingMode = bp.mRebufferingMode;
+
+            mInitialWatermarkMs = bp.mInitialWatermarkMs;
+            mInitialWatermarkKB = bp.mInitialWatermarkKB;
+
+            mRebufferingWatermarkLowMs = bp.mRebufferingWatermarkLowMs;
+            mRebufferingWatermarkHighMs = bp.mRebufferingWatermarkHighMs;
+            mRebufferingWatermarkLowKB = bp.mRebufferingWatermarkLowKB;
+            mRebufferingWatermarkHighKB = bp.mRebufferingWatermarkHighKB;
+        }
+
+        /**
+         * Combines all of the fields that have been set and return a new
+         * {@link BufferingParams} object. <code>IllegalStateException</code> will be
+         * thrown if there is conflict between fields.
+         * @return a new {@link BufferingParams} object
+         */
+        public BufferingParams build() {
+            if (isTimeBasedMode(mRebufferingMode)
+                    && mRebufferingWatermarkLowMs > mRebufferingWatermarkHighMs) {
+                throw new IllegalStateException("Illegal watermark:"
+                        + mRebufferingWatermarkLowMs + " : " + mRebufferingWatermarkHighMs);
+            }
+            if (isSizeBasedMode(mRebufferingMode)
+                    && mRebufferingWatermarkLowKB > mRebufferingWatermarkHighKB) {
+                throw new IllegalStateException("Illegal watermark:"
+                        + mRebufferingWatermarkLowKB + " : " + mRebufferingWatermarkHighKB);
+            }
+
+            BufferingParams bp = new BufferingParams();
+            bp.mInitialBufferingMode = mInitialBufferingMode;
+            bp.mRebufferingMode = mRebufferingMode;
+
+            bp.mInitialWatermarkMs = mInitialWatermarkMs;
+            bp.mInitialWatermarkKB = mInitialWatermarkKB;
+
+            bp.mRebufferingWatermarkLowMs = mRebufferingWatermarkLowMs;
+            bp.mRebufferingWatermarkHighMs = mRebufferingWatermarkHighMs;
+            bp.mRebufferingWatermarkLowKB = mRebufferingWatermarkLowKB;
+            bp.mRebufferingWatermarkHighKB = mRebufferingWatermarkHighKB;
+            return bp;
+        }
+
+        private boolean isTimeBasedMode(int mode) {
+            return (mode == BUFFERING_MODE_TIME_ONLY || mode == BUFFERING_MODE_TIME_THEN_SIZE);
+        }
+
+        private boolean isSizeBasedMode(int mode) {
+            return (mode == BUFFERING_MODE_SIZE_ONLY || mode == BUFFERING_MODE_TIME_THEN_SIZE);
+        }
+
+        /**
+         * Sets the initial buffering mode.
+         * @param mode one of {@link BufferingParams#BUFFERING_MODE_NONE},
+         *     {@link BufferingParams#BUFFERING_MODE_TIME_ONLY},
+         *     {@link BufferingParams#BUFFERING_MODE_SIZE_ONLY},
+         *     {@link BufferingParams#BUFFERING_MODE_TIME_THEN_SIZE},
+         * @return the same Builder instance.
+         */
+        public Builder setInitialBufferingMode(@BufferingMode int mode) {
+            switch (mode) {
+                case BUFFERING_MODE_NONE:
+                case BUFFERING_MODE_TIME_ONLY:
+                case BUFFERING_MODE_SIZE_ONLY:
+                case BUFFERING_MODE_TIME_THEN_SIZE:
+                     mInitialBufferingMode = mode;
+                     break;
+                default:
+                     throw new IllegalArgumentException("Illegal buffering mode " + mode);
+            }
+            return this;
+        }
+
+        /**
+         * Sets the rebuffering mode.
+         * @param mode one of {@link BufferingParams#BUFFERING_MODE_NONE},
+         *     {@link BufferingParams#BUFFERING_MODE_TIME_ONLY},
+         *     {@link BufferingParams#BUFFERING_MODE_SIZE_ONLY},
+         *     {@link BufferingParams#BUFFERING_MODE_TIME_THEN_SIZE},
+         * @return the same Builder instance.
+         */
+        public Builder setRebufferingMode(@BufferingMode int mode) {
+            switch (mode) {
+                case BUFFERING_MODE_NONE:
+                case BUFFERING_MODE_TIME_ONLY:
+                case BUFFERING_MODE_SIZE_ONLY:
+                case BUFFERING_MODE_TIME_THEN_SIZE:
+                     mRebufferingMode = mode;
+                     break;
+                default:
+                     throw new IllegalArgumentException("Illegal buffering mode " + mode);
+            }
+            return this;
+        }
+
+        /**
+         * Sets the time based watermark in milliseconds for initial buffering.
+         * @param watermarkMs time based watermark in milliseconds
+         * @return the same Builder instance.
+         */
+        public Builder setInitialBufferingWatermarkMs(int watermarkMs) {
+            mInitialWatermarkMs = watermarkMs;
+            return this;
+        }
+
+        /**
+         * Sets the size based watermark in kilobytes for initial buffering.
+         * @param watermarkKB size based watermark in kilobytes
+         * @return the same Builder instance.
+         */
+        public Builder setInitialBufferingWatermarkKB(int watermarkKB) {
+            mInitialWatermarkKB = watermarkKB;
+            return this;
+        }
+
+        /**
+         * Sets the time based low watermark in milliseconds for rebuffering.
+         * @param watermarkMs time based low watermark in milliseconds
+         * @return the same Builder instance.
+         */
+        public Builder setRebufferingWatermarkLowMs(int watermarkMs) {
+            mRebufferingWatermarkLowMs = watermarkMs;
+            return this;
+        }
+
+        /**
+         * Sets the time based high watermark in milliseconds for rebuffering.
+         * @param watermarkMs time based high watermark in milliseconds
+         * @return the same Builder instance.
+         */
+        public Builder setRebufferingWatermarkHighMs(int watermarkMs) {
+            mRebufferingWatermarkHighMs = watermarkMs;
+            return this;
+        }
+
+        /**
+         * Sets the size based low watermark in milliseconds for rebuffering.
+         * @param watermarkKB size based low watermark in milliseconds
+         * @return the same Builder instance.
+         */
+        public Builder setRebufferingWatermarkLowKB(int watermarkKB) {
+            mRebufferingWatermarkLowKB = watermarkKB;
+            return this;
+        }
+
+        /**
+         * Sets the size based high watermark in milliseconds for rebuffering.
+         * @param watermarkKB size based high watermark in milliseconds
+         * @return the same Builder instance.
+         */
+        public Builder setRebufferingWatermarkHighKB(int watermarkKB) {
+            mRebufferingWatermarkHighKB = watermarkKB;
+            return this;
+        }
+
+        /**
+         * Sets the time based low and high watermarks in milliseconds for rebuffering.
+         * @param lowWatermarkMs time based low watermark in milliseconds
+         * @param highWatermarkMs time based high watermark in milliseconds
+         * @return the same Builder instance.
+         */
+        public Builder setRebufferingWatermarksMs(int lowWatermarkMs, int highWatermarkMs) {
+            mRebufferingWatermarkLowMs = lowWatermarkMs;
+            mRebufferingWatermarkHighMs = highWatermarkMs;
+            return this;
+        }
+
+        /**
+         * Sets the size based low and high watermarks in kilobytes for rebuffering.
+         * @param lowWatermarkKB size based low watermark in kilobytes
+         * @param highWatermarkKB size based high watermark in kilobytes
+         * @return the same Builder instance.
+         */
+        public Builder setRebufferingWatermarksKB(int lowWatermarkKB, int highWatermarkKB) {
+            mRebufferingWatermarkLowKB = lowWatermarkKB;
+            mRebufferingWatermarkHighKB = highWatermarkKB;
+            return this;
+        }
+    }
+
+    private BufferingParams(Parcel in) {
+        mInitialBufferingMode = in.readInt();
+        mRebufferingMode = in.readInt();
+
+        mInitialWatermarkMs = in.readInt();
+        mInitialWatermarkKB = in.readInt();
+
+        mRebufferingWatermarkLowMs = in.readInt();
+        mRebufferingWatermarkHighMs = in.readInt();
+        mRebufferingWatermarkLowKB = in.readInt();
+        mRebufferingWatermarkHighKB = in.readInt();
+    }
+
+    public static final Parcelable.Creator<BufferingParams> CREATOR =
+            new Parcelable.Creator<BufferingParams>() {
+                @Override
+                public BufferingParams createFromParcel(Parcel in) {
+                    return new BufferingParams(in);
+                }
+
+                @Override
+                public BufferingParams[] newArray(int size) {
+                    return new BufferingParams[size];
+                }
+            };
+
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mInitialBufferingMode);
+        dest.writeInt(mRebufferingMode);
+
+        dest.writeInt(mInitialWatermarkMs);
+        dest.writeInt(mInitialWatermarkKB);
+
+        dest.writeInt(mRebufferingWatermarkLowMs);
+        dest.writeInt(mRebufferingWatermarkHighMs);
+        dest.writeInt(mRebufferingWatermarkLowKB);
+        dest.writeInt(mRebufferingWatermarkHighKB);
+    }
+}
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 52d5b7ca..71f7790 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -1597,8 +1597,8 @@
                         final Rational[] rationalArray = new Rational[values.length];
                         for (int j = 0; j < values.length; ++j) {
                             final String[] numbers = values[j].split("/");
-                            rationalArray[j] = new Rational(Long.parseLong(numbers[0]),
-                                    Long.parseLong(numbers[1]));
+                            rationalArray[j] = new Rational((long) Double.parseDouble(numbers[0]),
+                                    (long) Double.parseDouble(numbers[1]));
                         }
                         mAttributes[i].put(tag,
                                 ExifAttribute.createURational(rationalArray, mExifByteOrder));
@@ -1609,8 +1609,8 @@
                         final Rational[] rationalArray = new Rational[values.length];
                         for (int j = 0; j < values.length; ++j) {
                             final String[] numbers = values[j].split("/");
-                            rationalArray[j] = new Rational(Long.parseLong(numbers[0]),
-                                    Long.parseLong(numbers[1]));
+                            rationalArray[j] = new Rational((long) Double.parseDouble(numbers[0]),
+                                    (long) Double.parseDouble(numbers[1]));
                         }
                         mAttributes[i].put(tag,
                                 ExifAttribute.createSRational(rationalArray, mExifByteOrder));
@@ -3442,8 +3442,8 @@
             String[] rationalNumber = entryValue.split("/");
             if (rationalNumber.length == 2) {
                 try {
-                    long numerator = Long.parseLong(rationalNumber[0]);
-                    long denominator = Long.parseLong(rationalNumber[1]);
+                    long numerator = (long) Double.parseDouble(rationalNumber[0]);
+                    long denominator = (long) Double.parseDouble(rationalNumber[1]);
                     if (numerator < 0L || denominator < 0L) {
                         return new Pair<>(IFD_FORMAT_SRATIONAL, -1);
                     }
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 264944f..75ccffe 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -3134,6 +3134,15 @@
     public native final String getName();
 
     /**
+     *  Returns Analytics/Metrics data about the current content being
+     *
+     * @return a Bundle containint the set of attributes and values available
+     * for the media being handled by this instance of MediaCodec
+     *
+     */
+    public native Bundle getMetrics();
+
+    /**
      * Change a video encoder's target bitrate on the fly. The value is an
      * Integer object containing the new bitrate in bps.
      */
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
index e481aa1..a1f816b 100644
--- a/media/java/android/media/MediaMuxer.java
+++ b/media/java/android/media/MediaMuxer.java
@@ -95,7 +95,8 @@
     public @interface Format {}
 
     // All the native functions are listed here.
-    private static native long nativeSetup(@NonNull FileDescriptor fd, int format);
+    private static native long nativeSetup(@NonNull FileDescriptor fd, int format)
+            throws IllegalArgumentException, IOException;
     private static native void nativeRelease(long nativeObject);
     private static native void nativeStart(long nativeObject);
     private static native void nativeStop(long nativeObject);
@@ -134,19 +135,13 @@
         if (path == null) {
             throw new IllegalArgumentException("path must not be null");
         }
-        if (format != OutputFormat.MUXER_OUTPUT_MPEG_4 &&
-                format != OutputFormat.MUXER_OUTPUT_WEBM) {
-            throw new IllegalArgumentException("format is invalid");
-        }
         // Use RandomAccessFile so we can open the file with RW access;
         // RW access allows the native writer to memory map the output file.
         RandomAccessFile file = null;
         try {
             file = new RandomAccessFile(path, "rws");
             FileDescriptor fd = file.getFD();
-            mNativeObject = nativeSetup(fd, format);
-            mState = MUXER_STATE_INITIALIZED;
-            mCloseGuard.open("release");
+            setUpMediaMuxer(fd, format);
         } finally {
             if (file != null) {
                 file.close();
@@ -155,6 +150,32 @@
     }
 
     /**
+     * Constructor.
+     * Creates a media muxer that writes to the specified FileDescriptor. File descriptor
+     * must be seekable and writable. Application should not use the file referenced
+     * by this file descriptor until {@link #stop}. It is the application's responsibility
+     * to close the file descriptor. It is safe to do so as soon as this call returns.
+     * @param fd The FileDescriptor of the output media file.
+     * @param format The format of the output media file.
+     * @see android.media.MediaMuxer.OutputFormat
+     * @throws IllegalArgumentException if fd is invalid or format is not supported.
+     * @throws IOException if failed to open the file for write.
+     */
+    public MediaMuxer(@NonNull FileDescriptor fd, @Format int format) throws IOException {
+        setUpMediaMuxer(fd, format);
+    }
+
+    private void setUpMediaMuxer(@NonNull FileDescriptor fd, @Format int format) throws IOException {
+        if (format != OutputFormat.MUXER_OUTPUT_MPEG_4 &&
+                format != OutputFormat.MUXER_OUTPUT_WEBM) {
+            throw new IllegalArgumentException("format: " + format + " is invalid");
+        }
+        mNativeObject = nativeSetup(fd, format);
+        mState = MUXER_STATE_INITIALIZED;
+        mCloseGuard.open("release");
+    }
+
+    /**
      * Sets the orientation hint for output video playback.
      * <p>This method should be called before {@link #start}. Calling this
      * method will not rotate the video frame when muxer is generating the file,
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index e3a0f25..62abdefd 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -25,6 +25,7 @@
 import android.content.Context;
 import android.content.res.AssetFileDescriptor;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
@@ -45,6 +46,8 @@
 import android.widget.VideoView;
 import android.graphics.SurfaceTexture;
 import android.media.AudioManager;
+import android.media.BufferingParams;
+import android.media.MediaDrm;
 import android.media.MediaFormat;
 import android.media.MediaTimeProvider;
 import android.media.PlaybackParams;
@@ -58,6 +61,7 @@
 
 import libcore.io.IoBridge;
 import libcore.io.Libcore;
+import libcore.io.Streams;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -68,13 +72,20 @@
 import java.lang.Runnable;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.WeakReference;
+import java.net.HttpURLConnection;
 import java.net.InetSocketAddress;
+import java.net.URL;
+import java.nio.ByteOrder;
+import java.util.Arrays;
 import java.util.BitSet;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.Scanner;
 import java.util.Set;
+import java.util.UUID;
 import java.util.Vector;
-import java.lang.ref.WeakReference;
+
 
 /**
  * MediaPlayer class can be used to control playback
@@ -479,6 +490,11 @@
  *     <td>{} </p></td>
  *     <td>This method can be called in any state and calling it does not change
  *         the object state. </p></td></tr>
+ * <tr><td>setBufferingParams</p></td>
+ *     <td>{Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted, Error}</p></td>
+ *     <td>{Idle} </p></td>
+ *     <td>This method does not change the object state.
+ *         </p></td></tr>
  * <tr><td>setPlaybackParams</p></td>
  *     <td>{Initialized, Prepared, Started, Paused, PlaybackCompleted, Error}</p></td>
  *     <td>{Idle, Stopped} </p></td>
@@ -618,6 +634,17 @@
     private int mUsage = -1;
     private boolean mBypassInterruptionPolicy;
 
+    // Modular DRM
+    private UUID mDrmUUID;
+    private final Object mDrmLock = new Object();
+    private DrmInfo mDrmInfo;
+    private boolean mDrmInfoResolved;
+    private boolean mActiveDrmScheme;
+    private boolean mDrmConfigAllowed;
+    private boolean mDrmProvisioningInProgress;
+    private boolean mPrepareDrmInProgress;
+    private ProvisioningThread mDrmProvisioningThread;
+
     /**
      * Default constructor. Consider using one of the create() methods for
      * synchronously instantiating a MediaPlayer from a Uri or resource.
@@ -1381,6 +1408,14 @@
     public native int getVideoHeight();
 
     /**
+     *  Returns Analytics/Metrics data about the current video in this player.
+     *
+     * @return the a map of attributes and values available for this video
+     * player or null if no metrics are available.
+     */
+    public native Bundle getMetrics();
+
+    /**
      * Checks whether the MediaPlayer is playing.
      *
      * @return true if currently playing, false otherwise
@@ -1390,6 +1425,45 @@
     public native boolean isPlaying();
 
     /**
+     * Gets the default buffering management params.
+     * Calling it only after {@code setDataSource} has been called.
+     * Each type of data source might have different set of default params.
+     *
+     * @return the default buffering management params supported by the source component.
+     * @throws IllegalStateException if the internal player engine has not been
+     * initialized, or {@code setDataSource} has not been called.
+     */
+    @NonNull
+    public native BufferingParams getDefaultBufferingParams();
+
+    /**
+     * Gets the current buffering management params used by the source component.
+     * Calling it only after {@code setDataSource} has been called.
+     *
+     * @return the current buffering management params used by the source component.
+     * @throws IllegalStateException if the internal player engine has not been
+     * initialized, or {@code setDataSource} has not been called.
+     */
+    @NonNull
+    public native BufferingParams getBufferingParams();
+
+    /**
+     * Sets buffering management params.
+     * The object sets its internal BufferingParams to the input, except that the input is
+     * invalid or not supported.
+     * Call it only after {@code setDataSource} has been called.
+     * Users should only use supported mode returned by {@link #getDefaultBufferingParams()}
+     * or its downsized version as described in {@link BufferingParams}.
+     *
+     * @param params the buffering management params.
+     *
+     * @throws IllegalStateException if the internal player engine has not been
+     * initialized or has been released, or {@code setDataSource} has not been called.
+     * @throws IllegalArgumentException if params is invalid or not supported.
+     */
+    public native void setBufferingParams(@NonNull BufferingParams params);
+
+    /**
      * Change playback speed of audio by resampling the audio.
      * <p>
      * Specifies resampling as audio mode for variable rate playback, i.e.,
@@ -1812,6 +1886,12 @@
             mTimeProvider = null;
         }
         mOnSubtitleDataListener = null;
+
+        // Modular DRM clean up
+        mOnDrmInfoHandlerDelegate = null;
+        mOnDrmPreparedHandlerDelegate = null;
+        resetDrmState();
+
         _release();
     }
 
@@ -1852,6 +1932,8 @@
             mIndexTrackPairs.clear();
             mInbandTrackIndices.clear();
         };
+
+        resetDrmState();
     }
 
     private native void _reset();
@@ -2945,6 +3027,7 @@
     private static final int MEDIA_INFO = 200;
     private static final int MEDIA_SUBTITLE_DATA = 201;
     private static final int MEDIA_META_DATA = 202;
+    private static final int MEDIA_DRM_INFO = 210;
 
     private TimeProvider mTimeProvider;
 
@@ -2983,11 +3066,43 @@
                             MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null);
                     sendMessage(msg2);
                 }
+
+                // MEDIA_DRM_INFO is fired (if available) before MEDIA_PREPARED.
+                // An empty mDrmInfo indicates prepared is done but the source is not DRM protected.
+                // Setting this before the callback so onPreparedListener can call getDrmInfo to
+                // get the right state
+                mDrmInfoResolved = true;
+
                 OnPreparedListener onPreparedListener = mOnPreparedListener;
                 if (onPreparedListener != null)
                     onPreparedListener.onPrepared(mMediaPlayer);
                 return;
 
+            case MEDIA_DRM_INFO:
+                Log.v(TAG, "MEDIA_DRM_INFO " + mOnDrmInfoHandlerDelegate);
+
+                if (msg.obj == null) {
+                    Log.w(TAG, "MEDIA_DRM_INFO msg.obj=NULL");
+                } else if (msg.obj instanceof Parcel) {
+                    Parcel parcel = (Parcel)msg.obj;
+                    DrmInfo drmInfo = new DrmInfo(parcel);
+
+                    OnDrmInfoHandlerDelegate onDrmInfoHandlerDelegate;
+                    synchronized (mDrmLock) {
+                        mDrmInfo = drmInfo.makeCopy();
+                        // local copy while keeping the lock
+                        onDrmInfoHandlerDelegate = mOnDrmInfoHandlerDelegate;
+                    }
+
+                    // notifying the client outside the lock
+                    if (onDrmInfoHandlerDelegate != null) {
+                        onDrmInfoHandlerDelegate.notifyClient(drmInfo);
+                    }
+                } else {
+                    Log.w(TAG, "MEDIA_DRM_INFO msg.obj NONE; UNEXPECTED" + msg.obj);
+                }
+                return;
+
             case MEDIA_PLAYBACK_COMPLETE:
                 {
                     mOnCompletionInternalListener.onCompletion(mMediaPlayer);
@@ -3646,6 +3761,988 @@
 
     private OnInfoListener mOnInfoListener;
 
+    // Modular DRM begin
+
+    /**
+     * Interface definition of a callback to be invoked when the app
+     * can do DRM configuration (get/set properties) before the session
+     * is opened. This facilitates configuration of the properties, like
+     * 'securityLevel', which has to be set after DRM scheme creation but
+     * before the DRM session is opened.
+     *
+     * The only allowed DRM calls in this listener are getDrmPropertyString
+     * and setDrmPropertyString.
+     *
+     */
+    public static abstract class OnDrmConfigCallback
+    {
+        /**
+         * Called to give the app the opportunity to configure DRM before the session is created
+         *
+         * @param mp the {@code MediaPlayer} associated with this callback
+         */
+        public void onDrmConfig(MediaPlayer mp) {}
+    }
+
+    /**
+     * Interface definition of a callback to be invoked when the
+     * DRM info becomes available
+     */
+    public interface OnDrmInfoListener
+    {
+        /**
+         * Called to indicate DRM info is available
+         *
+         * @param mp the {@code MediaPlayer} associated with this callback
+         * @param drmInfo DRM info of the source including PSSH, mimes, and subset
+         *                of crypto schemes supported by this device
+         */
+        public void onDrmInfo(MediaPlayer mp, DrmInfo drmInfo);
+    }
+
+    /**
+     * Register a callback to be invoked when the DRM info is
+     * known.
+     *
+     * @param listener the callback that will be run
+     */
+    public void setOnDrmInfoListener(OnDrmInfoListener listener)
+    {
+        setOnDrmInfoListener(listener, null);
+    }
+
+    /**
+     * Register a callback to be invoked when the DRM info is
+     * known.
+     *
+     * @param listener the callback that will be run
+     */
+    public void setOnDrmInfoListener(OnDrmInfoListener listener, Handler handler)
+    {
+        synchronized (mDrmLock) {
+            if (listener != null) {
+                mOnDrmInfoHandlerDelegate = new OnDrmInfoHandlerDelegate(this, listener, handler);
+            } else {
+                mOnDrmInfoHandlerDelegate = null;
+            }
+        } // synchronized
+    }
+
+    private OnDrmInfoHandlerDelegate mOnDrmInfoHandlerDelegate;
+
+    /**
+     * Interface definition of a callback to notify the app when the
+     * DRM is ready for key request/response
+     */
+    public interface OnDrmPreparedListener
+    {
+        /**
+         * Called to notify the app that prepareDrm is finished and ready for key request/response
+         *
+         * @param mp the {@code MediaPlayer} associated with this callback
+         * @param success the result of DRM preparation
+         */
+        public void onDrmPrepared(MediaPlayer mp, boolean success);
+    }
+
+    /**
+     * Register a callback to be invoked when the DRM object is prepared.
+     *
+     * @param listener the callback that will be run
+     */
+    public void setOnDrmPreparedListener(OnDrmPreparedListener listener)
+    {
+        setOnDrmPreparedListener(listener, null);
+    }
+
+    /**
+     * Register a callback to be invoked when the DRM object is prepared.
+     *
+     * @param listener the callback that will be run
+     * @param handler the Handler that will receive the callback
+     */
+    public void setOnDrmPreparedListener(OnDrmPreparedListener listener, Handler handler)
+    {
+        synchronized (mDrmLock) {
+            if (listener != null) {
+                mOnDrmPreparedHandlerDelegate = new OnDrmPreparedHandlerDelegate(this,
+                                                            listener, handler);
+            } else {
+                mOnDrmPreparedHandlerDelegate = null;
+            }
+        } // synchronized
+    }
+
+    private OnDrmPreparedHandlerDelegate mOnDrmPreparedHandlerDelegate;
+
+
+    private class OnDrmInfoHandlerDelegate {
+        private MediaPlayer mMediaPlayer;
+        private OnDrmInfoListener mOnDrmInfoListener;
+        private Handler mHandler;
+
+        OnDrmInfoHandlerDelegate(MediaPlayer mp, OnDrmInfoListener listener, Handler handler) {
+            mMediaPlayer = mp;
+            mOnDrmInfoListener = listener;
+
+            // find the looper for our new event handler
+            Looper looper = null;
+            if (handler != null) {
+                looper = handler.getLooper();
+            }
+
+            // construct the event handler with this looper
+            if (looper != null) {
+                // implement the event handler delegate
+                mHandler = new Handler(looper) {
+                    public void handleMessage(Message msg) {
+                        DrmInfo drmInfo = (DrmInfo)msg.obj;
+                        mOnDrmInfoListener.onDrmInfo(mMediaPlayer, drmInfo);
+                    }
+                };
+            }
+        }
+
+        void notifyClient(DrmInfo drmInfo) {
+            if ( mHandler != null ) {
+                Message msg = new Message();  // no message type needed
+                msg.obj = drmInfo;
+                mHandler.sendMessage(msg);
+            }
+            else {  // no handler: direct call
+                mOnDrmInfoListener.onDrmInfo(mMediaPlayer, drmInfo);
+            }
+        }
+    }
+
+    private class OnDrmPreparedHandlerDelegate {
+        private MediaPlayer mMediaPlayer;
+        private OnDrmPreparedListener mOnDrmPreparedListener;
+        private Handler mHandler;
+
+        OnDrmPreparedHandlerDelegate(MediaPlayer mp, OnDrmPreparedListener listener,
+                Handler handler) {
+            mMediaPlayer = mp;
+            mOnDrmPreparedListener = listener;
+
+            // find the looper for our new event handler
+            Looper looper = null;
+            if (handler != null) {
+                looper = handler.getLooper();
+            }
+
+            // construct the event handler with this looper
+            if (looper != null) {
+                // implement the event handler delegate
+                mHandler = new Handler(looper) {
+                    public void handleMessage(Message msg) {
+                        boolean success = (msg.arg1 == 0) ? false : true;
+                        mOnDrmPreparedListener.onDrmPrepared(mMediaPlayer, success);
+                    }
+                };
+            }
+        }
+
+        void notifyClient(boolean success) {
+            if ( mHandler != null ) {
+                Message msg = new Message();  // no message type needed
+                msg.arg1 = success ? 1 : 0;
+                mHandler.sendMessage(msg);
+            }
+            else {  // no handler: direct call
+                mOnDrmPreparedListener.onDrmPrepared(mMediaPlayer, success);
+            }
+        }
+    }
+
+    /**
+     * Retrieves the DRM Info associated with the current source
+     *
+     * @throws IllegalStateException if called before prepare()
+     */
+    public DrmInfo getDrmInfo()
+    {
+        DrmInfo drmInfo = null;
+
+        // there is not much point if the app calls getDrmInfo within an OnDrmInfoListenet;
+        // regardless below returns drmInfo anyway instead of raising an exception
+        synchronized (mDrmLock) {
+            if (!mDrmInfoResolved && mDrmInfo == null) {
+                final String msg = "The Player has not been prepared yet";
+                Log.v(TAG, msg);
+                throw new IllegalStateException(msg);
+            }
+
+            if (mDrmInfo != null) {
+                drmInfo = mDrmInfo.makeCopy();
+            }
+        }   // synchronized
+
+        return drmInfo;
+    }
+
+    private native void _prepareDrm(@NonNull byte[] uuid, int mode)
+            throws UnsupportedSchemeException, ResourceBusyException, NotProvisionedException;
+
+    /**
+     * Prepares the DRM for the current source
+     * <p>
+     * If {@code OnDrmConfigCallback} is registered, it will be called half-way into
+     * preparation to allow configuration of the DRM properties before opening the
+     * DRM session. Note that the callback is called synchronously in the thread that called
+     * {@code prepareDrm}. It should be used only for a series of {@code getDrmPropertyString}
+     * and {@code setDrmPropertyString} calls and refrain from any lengthy operation.
+     * <p>
+     * If the device has not been provisioned before, this call also provisions the device
+     * which involves accessing the provisioning server and can take a variable time to
+     * complete depending on the network connectivity.
+     * If OnDrmPreparedListener is registered, prepareDrm() runs in non-blocking
+     * mode by launching the provisioning in the background and returning. The listener
+     * will be called when provisioning and preperation has finished. If a
+     * OnDrmPreparedListener is not registered, prepareDrm() waits till provisioning
+     * and preperation has finished, i.e., runs in blocking mode.
+     * <p>
+     * If OnDrmPreparedListener is registered, it is called to indicated the DRM session
+     * being ready regardless of blocking or non-blocking mode. The application should
+     * not make any assumption about its call sequence (e.g., before or after prepareDrm
+     * returns) or the thread context that will execute the listener.
+     * <p>
+     *
+     * @param uuid The UUID of the crypto scheme.
+     *
+     * @throws IllegalStateException       if called before prepare(), or there exists a Drm already
+     * @throws UnsupportedSchemeException  if the crypto scheme is not supported
+     * @throws ResourceBusyException       if required DRM resources are in use
+     * @throws ProvisioningErrorException  if provisioning is required but an attempt failed
+     */
+    public void prepareDrm(@NonNull UUID uuid, OnDrmConfigCallback configCallback)
+            throws UnsupportedSchemeException,
+                   ResourceBusyException, ProvisioningErrorException
+    {
+        boolean allDoneWithoutProvisioning = false;
+        // get a snapshot as we'll use them outside the lock
+        OnDrmPreparedHandlerDelegate onDrmPreparedHandlerDelegate = null;
+
+        synchronized (mDrmLock) {
+
+            // only allowing if tied to a protected source; might releax for releasing offline keys
+            if (mDrmInfo == null) {
+                final String msg = String.format("prepareDrm(%s): Wrong usage: " +
+                                                 "The player must be prepared and DRM " +
+                                                 "info be retrieved before this call.", uuid);
+                Log.e(TAG, msg);
+                throw new IllegalStateException(msg);
+            }
+
+            if (mActiveDrmScheme) {
+                final String msg = String.format("prepareDrm(%s): Wrong usage: There is already " +
+                                                 "an active DRM scheme with %s.", uuid, mDrmUUID);
+                Log.e(TAG, msg);
+                throw new IllegalStateException(msg);
+            }
+
+            if (mPrepareDrmInProgress) {
+                final String msg = String.format("prepareDrm(%s): Wrong usage: There is already " +
+                                                 "a pending prepareDrm call.", uuid);
+                Log.e(TAG, msg);
+                throw new IllegalStateException(msg);
+            }
+
+            if (mDrmProvisioningInProgress) {
+                final String msg = String.format("prepareDrm(%s): Unexpectd: Provisioning is " +
+                                                 "already in progress.", uuid);
+                Log.e(TAG, msg);
+                throw new IllegalStateException(msg);
+            }
+
+            mPrepareDrmInProgress = true;
+            // local copy while the lock is held
+            onDrmPreparedHandlerDelegate = mOnDrmPreparedHandlerDelegate;
+
+            if (configCallback != null) {
+                try {
+                    boolean allowOpenSession = false;   // just pre-openSession
+                    _prepareDrm(getByteArrayFromUUID(uuid), allowOpenSession ? 1 : 0);
+                } catch (IllegalStateException e) {
+                    final String msg = String.format("prepareDrm(): Wrong usage: The player must " +
+                                                     "be in prepared state to call prepareDrm().");
+                    Log.e(TAG, msg);
+                    throw new IllegalStateException(msg);
+                } catch (NotProvisionedException e) {   // the pre-config step won't raise this
+                    final String msg = String.format("prepareDrm: Unexpected " +
+                                                     "NotProvisionedException here.");
+                    Log.e(TAG, msg);
+                    throw new ProvisioningErrorException(msg);
+                } catch (Exception e) {
+                    Log.w(TAG, String.format("prepareDrm: Exception %s", e));
+                    throw e;
+                } finally {
+                    mPrepareDrmInProgress = false;
+                }
+            }
+
+            mDrmConfigAllowed = true;
+        }   // synchronized
+
+
+        // call the callback outside the lock
+        if (configCallback != null)  {
+            configCallback.onDrmConfig(this);
+        }
+
+        synchronized (mDrmLock) {
+            mDrmConfigAllowed = false;
+
+            try {
+                boolean allowOpenSession = true;    // all in
+                _prepareDrm(getByteArrayFromUUID(uuid), allowOpenSession ? 1 : 0);
+
+                mDrmUUID = uuid;
+                mActiveDrmScheme = true;
+
+                mPrepareDrmInProgress = false;
+
+                allDoneWithoutProvisioning = true;
+            } catch (IllegalStateException e) {
+                final String msg = String.format("prepareDrm(%s): Wrong usage: The player must be" +
+                                                 " in prepared state to call prepareDrm().", uuid);
+                Log.e(TAG, msg);
+                throw new IllegalStateException(msg);
+            } catch (NotProvisionedException e) {
+                Log.w(TAG, String.format("prepareDrm: NotProvisionedException"));
+
+                // handle provisioning internally
+                boolean result = HandleProvisioninig(uuid);
+
+                // if blocking mode, we're already done;
+                // if non-blocking mode, we attempted to launch background provisioning
+                if (result == false) {
+                    final String msg =
+                                String.format("prepareDrm: Provisioning was required but failed.");
+                    Log.e(TAG, msg);
+                    throw new ProvisioningErrorException(msg);
+                }
+
+                // nothing else to do;
+                // if blocking or non-blocking, HandleProvisioninig does the re-attempt & cleanup
+            } catch (Exception e) {
+                Log.w(TAG, String.format("prepareDrm: Exception %s", e));
+                throw e;
+            } finally {
+                mPrepareDrmInProgress = false;
+            }
+        }   // synchronized
+
+
+        // if finished successfully without provisioning, call the callback outside the lock
+        if (allDoneWithoutProvisioning) {
+            if (onDrmPreparedHandlerDelegate != null)
+                onDrmPreparedHandlerDelegate.notifyClient(true /*success*/);
+        }
+
+    }
+
+
+    private native void _releaseDrm();
+
+    /**
+     * Releases the DRM session
+     *
+     * @throws NoDrmSchemeException if there is no active DRM session to release
+     */
+    public void releaseDrm()
+            throws NoDrmSchemeException
+    {
+        synchronized (mDrmLock) {
+            if (!mActiveDrmScheme) {
+                Log.e(TAG, String.format("releaseDrm(%s): No active DRM scheme to release."));
+                throw new NoDrmSchemeException("releaseDrm: No active DRM scheme to release.");
+            } else {
+                _releaseDrm();
+
+                mActiveDrmScheme = false;
+            }
+        }   // synchronized
+    }
+
+
+    @NonNull
+    private native MediaDrm.KeyRequest _getKeyRequest(@NonNull byte[] scope,
+            @Nullable String mimeType, @MediaDrm.KeyType int keyType,
+            @Nullable Map<String, String> optionalParameters)
+            throws NotProvisionedException;
+
+    /**
+     * A key request/response exchange occurs between the app and a license server
+     * to obtain or release keys used to decrypt encrypted content.
+     * <p>
+     * getKeyRequest() is used to obtain an opaque key request byte array that is
+     * delivered to the license server.  The opaque key request byte array is returned
+     * in KeyRequest.data.  The recommended URL to deliver the key request to is
+     * returned in KeyRequest.defaultUrl.
+     * <p>
+     * After the app has received the key request response from the server,
+     * it should deliver to the response to the DRM engine plugin using the method
+     * {@link #provideKeyResponse}.
+     *
+     * @param scope may be a container-specific initialization data or a keySetId,
+     * depending on the specified keyType.
+     * When the keyType is KEY_TYPE_STREAMING or KEY_TYPE_OFFLINE, scope should be set to
+     * the container-specific initialization data. Its meaning is interpreted based on the
+     * mime type provided in the mimeType parameter.  It could contain, for example,
+     * the content ID, key ID or other data obtained from the content metadata that is
+     * required in generating the key request.
+     * When the keyType is KEY_TYPE_RELEASE, scope should be set to the keySetId of
+     * the keys being released.
+     *
+     * @param mimeType identifies the mime type of the content
+     *
+     * @param keyType specifes the type of the request. The request may be to acquire
+     * keys for streaming or offline content, or to release previously acquired
+     * keys, which are identified by a keySetId.
+     *
+     * @param optionalParameters are included in the key request message to
+     * allow a client application to provide additional message parameters to the server.
+     * This may be {@code null} if no additional parameters are to be sent.
+     *
+     * @throws NoDrmSchemeException if there is no active DRM session
+     */
+    @NonNull
+    public MediaDrm.KeyRequest getKeyRequest(@NonNull byte[] scope, @Nullable String mimeType,
+            @MediaDrm.KeyType int keyType, @Nullable Map<String, String> optionalParameters)
+            throws NoDrmSchemeException
+    {
+        synchronized (mDrmLock) {
+            if (!mActiveDrmScheme) {
+                Log.e(TAG, String.format("getKeyRequest NoDrmSchemeException"));
+                throw new NoDrmSchemeException("getKeyRequest: Has to set a DRM scheme first.");
+            }
+
+            try {
+                return _getKeyRequest(scope, mimeType, keyType, optionalParameters);
+            } catch (NotProvisionedException e) {
+                Log.w(TAG, String.format("getKeyRequest NotProvisionedException: " +
+                                         "Unexpected. Shouldn't have reached here."));
+                throw new IllegalStateException("getKeyRequest: Unexpected provisioning error.");
+            } catch (Exception e) {
+                Log.w(TAG, String.format("getKeyRequest Exception %s", e));
+                throw e;
+            }
+
+        }   // synchronized
+    }
+
+
+    @Nullable
+    private native byte[] _provideKeyResponse(@Nullable byte[] keySetId, @NonNull byte[] response)
+            throws DeniedByServerException;
+
+    /**
+     * A key response is received from the license server by the app, then it is
+     * provided to the DRM engine plugin using provideKeyResponse. When the
+     * response is for an offline key request, a key-set identifier is returned that
+     * can be used to later restore the keys to a new session with the method
+     * {@ link # restoreKeys}.
+     * When the response is for a streaming or release request, null is returned.
+     *
+     * @param keySetId When the response is for a release request, keySetId identifies
+     * the saved key associated with the release request (i.e., the same keySetId
+     * passed to the earlier {@ link # getKeyRequest} call. It MUST be null when the
+     * response is for either streaming or offline key requests.
+     *
+     * @param response the byte array response from the server
+     *
+     * @throws NoDrmSchemeException if there is no active DRM session
+     * @throws DeniedByServerException if the response indicates that the
+     * server rejected the request
+     */
+    public byte[] provideKeyResponse(@Nullable byte[] keySetId, @NonNull byte[] response)
+            throws NoDrmSchemeException, DeniedByServerException
+    {
+        synchronized (mDrmLock) {
+
+            if (!mActiveDrmScheme) {
+                Log.e(TAG, String.format("getKeyRequest NoDrmSchemeException"));
+                throw new NoDrmSchemeException("getKeyRequest: Has to set a DRM scheme first.");
+            }
+
+            try {
+                return _provideKeyResponse(keySetId, response);
+            } catch (Exception e) {
+                Log.w(TAG, String.format("provideKeyResponse Exception %s", e));
+                throw e;
+            }
+        }   // synchronized
+    }
+
+
+    private native void _restoreKeys(@NonNull byte[] keySetId);
+
+    /**
+     * Restore persisted offline keys into a new session.  keySetId identifies the
+     * keys to load, obtained from a prior call to {@link #provideKeyResponse}.
+     *
+     * @param keySetId identifies the saved key set to restore
+     */
+    public void restoreKeys(@NonNull byte[] keySetId)
+            throws NoDrmSchemeException
+    {
+        synchronized (mDrmLock) {
+
+            if (!mActiveDrmScheme) {
+                Log.w(TAG, String.format("restoreKeys NoDrmSchemeException"));
+                throw new NoDrmSchemeException("restoreKeys: Has to set a DRM scheme first.");
+            }
+
+            try {
+                _restoreKeys(keySetId);
+            } catch (Exception e) {
+                Log.w(TAG, String.format("restoreKeys Exception %s", e));
+                throw e;
+            }
+
+        }   // synchronized
+    }
+
+
+    @NonNull
+    private native String _getDrmPropertyString(@NonNull String propertyName);
+
+    /**
+     * Read a DRM engine plugin String property value, given the property name string.
+     * <p>
+     * @param propertyName the property name
+     *
+     * Standard fields names are:
+     * {link #PROPERTY_VENDOR}, {link #PROPERTY_VERSION},
+     * {link #PROPERTY_DESCRIPTION}, {link #PROPERTY_ALGORITHMS}
+     */
+    @NonNull
+    public String getDrmPropertyString(@NonNull @MediaDrm.StringProperty String propertyName)
+            throws NoDrmSchemeException
+    {
+        String value;
+        synchronized (mDrmLock) {
+
+            if (!mActiveDrmScheme && !mDrmConfigAllowed) {
+                Log.w(TAG, String.format("getDrmPropertyString NoDrmSchemeException"));
+                throw new NoDrmSchemeException("getDrmPropertyString: Has to prepareDrm() first.");
+            }
+
+            try {
+                value = _getDrmPropertyString(propertyName);
+            } catch (Exception e) {
+                Log.w(TAG, String.format("getDrmPropertyString Exception %s", e));
+                throw e;
+            }
+        }   // synchronized
+
+        return value;
+    }
+
+    private native void _setDrmPropertyString(@NonNull String propertyName, @NonNull String value);
+
+    /**
+     * Set a DRM engine plugin String property value.
+     * <p>
+     * @param propertyName the property name
+     * @param value the property value
+     *
+     * Standard fields names are:
+     * {link #PROPERTY_VENDOR}, {link #PROPERTY_VERSION},
+     * {link #PROPERTY_DESCRIPTION}, {link #PROPERTY_ALGORITHMS}
+     */
+    public void setDrmPropertyString(@NonNull @MediaDrm.StringProperty String propertyName,
+                                     @NonNull String value)
+            throws NoDrmSchemeException
+    {
+        synchronized (mDrmLock) {
+
+            if ( !mActiveDrmScheme && !mDrmConfigAllowed ) {
+                Log.w(TAG, String.format("setDrmPropertyString NoDrmSchemeException"));
+                throw new NoDrmSchemeException("setDrmPropertyString: Has to prepareDrm() first.");
+            }
+
+            try {
+                _setDrmPropertyString(propertyName, value);
+            } catch ( Exception e ) {
+                Log.w(TAG, String.format("setDrmPropertyString Exception %s", e));
+                throw e;
+            }
+        }   // synchronized
+    }
+
+    public static final class DrmInfo {
+        private Map<UUID, byte[]> mapPssh;
+        private UUID[] supportedSchemes;
+        // TODO: Won't need this in final release. Only keeping it for the existing test app.
+        private String[] mimes;
+
+        public Map<UUID, byte[]> getPssh() {
+            return mapPssh;
+        }
+        public UUID[] getSupportedSchemes() {
+            return supportedSchemes;
+        }
+        // TODO: Won't need this in final release. Only keeping it for the existing test app.
+        public String[] getMimes() {
+            return mimes;
+        }
+
+        private DrmInfo(Map<UUID, byte[]> Pssh, UUID[] SupportedSchemes, String[] Mimes) {
+            mapPssh = Pssh;
+            supportedSchemes = SupportedSchemes;
+            mimes = Mimes;
+        }
+
+        private DrmInfo(Parcel parcel) {
+            Log.v(TAG, "DrmInfo(" + parcel + ") size " + parcel.dataSize());
+
+            int psshsize = parcel.readInt();
+            byte[] pssh = new byte[psshsize];
+            parcel.readByteArray(pssh);
+
+            Log.v(TAG, "DrmInfo() PSSH: " + arrToHex(pssh));
+            mapPssh = parsePSSH(pssh, psshsize);
+            Log.v(TAG, "DrmInfo() PSSH: " + mapPssh);
+
+            int supportedDRMsCount = parcel.readInt();
+            supportedSchemes = new UUID[supportedDRMsCount];
+            for (int i = 0; i < supportedDRMsCount; i++) {
+                byte[] uuid = new byte[16];
+                parcel.readByteArray(uuid);
+
+                supportedSchemes[i] = bytesToUUID(uuid);
+
+                Log.v(TAG, "DrmInfo() supportedScheme[" + i + "]: " +
+                      supportedSchemes[i]);
+            }
+
+            // TODO: Won't need this in final release. Only keeping it for the test app.
+            mimes = parcel.readStringArray();
+            int mimeCount = mimes.length;
+            Log.v(TAG, "DrmInfo() mime: " + Arrays.toString(mimes));
+
+            Log.v(TAG, "DrmInfo() Parcel psshsize: " + psshsize +
+                  " supportedDRMsCount: " + supportedDRMsCount +
+                  " mimeCount: " + mimeCount);
+        }
+
+        private DrmInfo makeCopy() {
+            return new DrmInfo(this.mapPssh, this.supportedSchemes, this.mimes);
+        }
+
+        private String arrToHex(byte[] bytes) {
+            String out = "0x";
+            for (int i = 0; i < bytes.length; i++) {
+                out += String.format("%02x", bytes[i]);
+            }
+
+            return out;
+        }
+
+        private UUID bytesToUUID(byte[] uuid) {
+            long msb = 0, lsb = 0;
+            for (int i = 0; i < 8; i++) {
+                msb |= ( ((long)uuid[i]   & 0xff) << (8 * (7 - i)) );
+                lsb |= ( ((long)uuid[i+8] & 0xff) << (8 * (7 - i)) );
+            }
+
+            return new UUID(msb, lsb);
+        }
+
+        private Map<UUID, byte[]> parsePSSH(byte[] pssh, int psshsize) {
+            Map<UUID, byte[]> result = new HashMap<UUID, byte[]>();
+
+            final int UUID_SIZE = 16;
+            final int DATALEN_SIZE = 4;
+
+            int len = psshsize;
+            int numentries = 0;
+            int i = 0;
+
+            while (len > 0) {
+                if (len < UUID_SIZE) {
+                    Log.w(TAG, String.format("parsePSSH: len is too short to parse " +
+                                             "UUID: (%d < 16) pssh: %d", len, psshsize));
+                    return null;
+                }
+
+                byte[] subset = Arrays.copyOfRange(pssh, i, i + UUID_SIZE);
+                UUID uuid = bytesToUUID(subset);
+                i += UUID_SIZE;
+                len -= UUID_SIZE;
+
+                // get data length
+                if (len < 4) {
+                    Log.w(TAG, String.format("parsePSSH: len is too short to parse " +
+                                             "datalen: (%d < 4) pssh: %d", len, psshsize));
+                    return null;
+                }
+
+                subset = Arrays.copyOfRange(pssh, i, i+DATALEN_SIZE);
+                int datalen = (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) ?
+                    ((subset[3] & 0xff) << 24) | ((subset[2] & 0xff) << 16) |
+                    ((subset[1] & 0xff) <<  8) |  (subset[0] & 0xff)          :
+                    ((subset[0] & 0xff) << 24) | ((subset[1] & 0xff) << 16) |
+                    ((subset[2] & 0xff) <<  8) |  (subset[3] & 0xff) ;
+                i += DATALEN_SIZE;
+                len -= DATALEN_SIZE;
+
+                if (len < datalen) {
+                    Log.w(TAG, String.format("parsePSSH: len is too short to parse " +
+                                             "data: (%d < %d) pssh: %d", len, datalen, psshsize));
+                    return null;
+                }
+
+                byte[] data = Arrays.copyOfRange(pssh, i, i+datalen);
+
+                // skip the data
+                i += datalen;
+                len -= datalen;
+
+                Log.v(TAG, String.format("parsePSSH[%d]: <%s, %s> pssh: %d",
+                                         numentries, uuid, arrToHex(data), psshsize));
+                numentries++;
+                result.put(uuid, data);
+            }
+
+            return result;
+        }
+
+    };  // DrmInfo
+
+    /**
+     * Thrown when a DRM method is called before preparing a DRM scheme through prepareDrm().
+     * Extends MediaDrm.MediaDrmException
+     */
+    public static final class NoDrmSchemeException extends MediaDrmException {
+        public NoDrmSchemeException(String detailMessage) {
+            super(detailMessage);
+        }
+    }
+
+    /**
+     * Thrown when the device requires DRM provisioning but the provisioning attempt has
+     * failed (for example: network timeout, provisioning server error).
+     * Extends MediaDrm.MediaDrmException
+     */
+    public static final class ProvisioningErrorException extends MediaDrmException {
+        public ProvisioningErrorException(String detailMessage) {
+            super(detailMessage);
+        }
+    }
+
+        // Modular DRM helpers
+
+    private class ProvisioningThread extends Thread
+    {
+        public static final int TIMEOUT_MS = 60000;
+
+        private UUID uuid;
+        private String urlStr;
+        private byte[] response;
+        private Object drmLock;
+        private OnDrmPreparedHandlerDelegate onDrmPreparedHandlerDelegate;
+        private MediaPlayer mediaPlayer;
+        private boolean succeeded;
+        private boolean finished;
+        public  boolean succeeded() {
+            return succeeded;
+        }
+
+        public ProvisioningThread initialize(MediaDrm.ProvisionRequest request,
+                                          UUID uuid, MediaPlayer mediaPlayer) {
+            // lock is held by the caller
+            drmLock = mediaPlayer.mDrmLock;
+            onDrmPreparedHandlerDelegate = mediaPlayer.mOnDrmPreparedHandlerDelegate;
+            this.mediaPlayer = mediaPlayer;
+
+            urlStr = request.getDefaultUrl() + "&signedRequest=" + new String(request.getData());
+            this.uuid = uuid;
+
+            Log.v(TAG, String.format("HandleProvisioninig: Thread is initialised url: %s", urlStr));
+            return this;
+        }
+
+        public void run() {
+
+            boolean provisioningSucceeded = false;
+            try {
+                URL url = new URL(urlStr);
+                final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+                try {
+                    connection.setRequestMethod("POST");
+                    connection.setDoOutput(false);
+                    connection.setDoInput(true);
+                    connection.setConnectTimeout(TIMEOUT_MS);
+                    connection.setReadTimeout(TIMEOUT_MS);
+
+                    connection.connect();
+                    response = Streams.readFully(connection.getInputStream());
+
+                    Log.v(TAG, String.format("HandleProvisioninig: Thread run response %d %s",
+                                             response.length, response));
+                } catch (Exception e) {
+                    Log.w(TAG, String.format("HandleProvisioninig: Thread run connect %s url: %s",
+                                             e, url));
+                } finally {
+                    connection.disconnect();
+                }
+            } catch (Exception e)   {
+                Log.w(TAG, String.format("HandleProvisioninig: Thread run openConnection %s", e));
+            }
+
+            if (response != null) {
+                try {
+                    MediaDrm drm = new MediaDrm(uuid);
+                    drm.provideProvisionResponse(response);
+                    drm.release();
+                    Log.v(TAG, String.format("HandleProvisioninig: Thread run " +
+                                             "newDrm+provideProvisionResponse SUCCEEDED!"));
+
+                    provisioningSucceeded = true;
+                } catch (Exception e)   {
+                    Log.w(TAG, String.format("HandleProvisioninig: Thread run " +
+                                             "newDrm+provideProvisionResponse %s", e));
+                }
+            }
+
+            // non-blocking mode needs the lock
+            if (onDrmPreparedHandlerDelegate != null) {
+
+                synchronized (drmLock) {
+                    // continuing with prepareDrm
+                    if (provisioningSucceeded) {
+                        succeeded = mediaPlayer.resumePrepareDrm(uuid);
+                    }
+                    mediaPlayer.mDrmProvisioningInProgress = false;
+                    mediaPlayer.mPrepareDrmInProgress = false;
+                }
+
+                // calling the callback outside the lock
+                onDrmPreparedHandlerDelegate.notifyClient(succeeded);
+            } else {   // blocking mode already has the lock
+
+                // continuing with prepareDrm
+                if (provisioningSucceeded) {
+                    succeeded = mediaPlayer.resumePrepareDrm(uuid);
+                }
+                mediaPlayer.mDrmProvisioningInProgress = false;
+                mediaPlayer.mPrepareDrmInProgress = false;
+            }
+
+            finished = true;
+        }   // run()
+
+    }   // ProvisioningThread
+
+    private boolean HandleProvisioninig(UUID uuid)
+    {
+        // the lock is already held by the caller
+
+        if (mDrmProvisioningInProgress) {
+            Log.e(TAG, String.format("HandleProvisioninig: Unexpected mDrmProvisioningInProgress"));
+            return false;
+        }
+
+        MediaDrm.ProvisionRequest provReq = null;
+        try {
+            MediaDrm drm = new MediaDrm(uuid);
+            provReq = drm.getProvisionRequest();
+            drm.release();
+        } catch (Exception e) {
+            Log.e(TAG, String.format("HandleProvisioninig: getProvisionRequest failed with %s", e));
+            return false;
+        }
+
+        Log.v(TAG, String.format("HandleProvisioninig provReq: data %s  url %s",
+                                 (provReq != null) ? provReq.getData() : "-",
+                                 (provReq != null) ? provReq.getDefaultUrl() : "://")
+              );
+
+        // networking in a background thread
+        mDrmProvisioningInProgress = true;
+
+        mDrmProvisioningThread = new ProvisioningThread().initialize(provReq, uuid, this);
+        mDrmProvisioningThread.start();
+
+        boolean result = false;
+
+        // non-blocking
+        if (mOnDrmPreparedHandlerDelegate != null) {
+            result = true;
+        } else {
+            // if blocking mode, wait till provisioning is done
+            try {
+                mDrmProvisioningThread.join();
+            } catch (Exception e) {
+                Log.w(TAG, String.format("HandleProvisioninig: Thread.join Exception %s", e));
+            }
+            result = mDrmProvisioningThread.succeeded();
+            // no longer need the thread
+            mDrmProvisioningThread = null;
+        }
+
+        return result;
+    }
+
+    private boolean resumePrepareDrm(UUID uuid)
+    {
+        // mDrmLock is guaranteed to be held
+        boolean success = false;
+        try {
+            boolean allowOpenSession = true;  // resuming
+            _prepareDrm(getByteArrayFromUUID(uuid),  allowOpenSession ? 1 : 0);
+
+            mDrmUUID = uuid;
+            mActiveDrmScheme = true;
+
+            success = true;
+        } catch (Exception e) {
+            Log.w(TAG, String.format("HandleProvisioninig: " +
+                                     "Thread run _prepareDrm resume failed with %s", e));
+        }
+
+        return success;
+    }
+
+    private void resetDrmState()
+    {
+        synchronized (mDrmLock) {
+            mDrmInfoResolved = false;
+            mDrmInfo = null;
+
+            if (mDrmProvisioningThread != null) {
+                // timeout; relying on HttpUrlConnection
+                try {
+                    mDrmProvisioningThread.join();
+                }
+                catch (InterruptedException e) {
+                    Log.w(TAG, String.format("resetDrmState: ProvThread.join Exception %s", e));
+                }
+                mDrmProvisioningThread = null;
+            }
+
+            mPrepareDrmInProgress = false;
+        }   // synchronized
+    }
+
+    private static final byte[] getByteArrayFromUUID(@NonNull UUID uuid) {
+        long msb = uuid.getMostSignificantBits();
+        long lsb = uuid.getLeastSignificantBits();
+
+        byte[] uuidBytes = new byte[16];
+        for (int i = 0; i < 8; ++i) {
+            uuidBytes[i] = (byte)(msb >>> (8 * (7 - i)));
+            uuidBytes[8 + i] = (byte)(lsb >>> (8 * (7 - i)));
+        }
+
+        return uuidBytes;
+    }
+
+    // Modular DRM end
+
     /*
      * Test whether a given video scaling mode is supported.
      */
diff --git a/media/java/android/media/MediaSyncEvent.java b/media/java/android/media/MediaSyncEvent.java
index 31af6b5..04448f0 100644
--- a/media/java/android/media/MediaSyncEvent.java
+++ b/media/java/android/media/MediaSyncEvent.java
@@ -36,7 +36,7 @@
      * The corresponding action is triggered only when the presentation is completed
      * (meaning the media has been presented to the user) on the specified session.
      * A synchronization of this type requires a source audio session ID to be set via
-     * {@link #setAudioSessionId(int) method.
+     * {@link #setAudioSessionId(int)} method.
      */
     public static final int SYNC_EVENT_PRESENTATION_COMPLETE =
                                                     AudioSystem.SYNC_EVENT_PRESENTATION_COMPLETE;
diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java
index e197141..5f12742 100644
--- a/media/java/android/media/audiopolicy/AudioMixingRule.java
+++ b/media/java/android/media/audiopolicy/AudioMixingRule.java
@@ -224,7 +224,7 @@
          *     {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}.
          * @return the same Builder instance.
          * @throws IllegalArgumentException
-         * @see {@link #excludeRule(AudioAttributes, int)}
+         * @see #excludeRule(AudioAttributes, int)
          */
         @SystemApi
         public Builder addRule(AudioAttributes attrToMatch, int rule)
@@ -253,7 +253,7 @@
          *     {@link AudioMixingRule#RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}.
          * @return the same Builder instance.
          * @throws IllegalArgumentException
-         * @see {@link #addRule(AudioAttributes, int)}
+         * @see #addRule(AudioAttributes, int)
          */
         @SystemApi
         public Builder excludeRule(AudioAttributes attrToMatch, int rule)
@@ -275,7 +275,7 @@
          *     {@link AudioAttributes} or an {@link java.lang.Integer}).
          * @return the same Builder instance.
          * @throws IllegalArgumentException
-         * @see {@link #excludeMixRule(int, Object)}
+         * @see #excludeMixRule(int, Object)
          */
         @SystemApi
         public Builder addMixRule(int rule, Object property) throws IllegalArgumentException {
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index 3ee80af..9a08fbe 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -654,7 +654,7 @@
          *
          * <p>This is used to indicate the broadcast standard (e.g. ATSC, DVB or ISDB) the current
          * channel conforms to. Use {@link #TYPE_OTHER} for streaming-based channels, which is the
-         * default channel type. The value should match to one of the followings:
+         * default channel type. The value should match one of the followings:
          * {@link #TYPE_1SEG},
          * {@link #TYPE_ATSC_C},
          * {@link #TYPE_ATSC_M_H},
@@ -1088,6 +1088,238 @@
         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
 
         /**
+         * The program type for movie.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_MOVIE = "TYPE_MOVIE";
+
+        /**
+         * The program type for TV series.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_TV_SERIES = "TYPE_TV_SERIES";
+
+        /**
+         * The program type for TV season.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_TV_SEASON = "TYPE_TV_SEASON";
+
+        /**
+         * The program type for TV episode.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_TV_EPISODE = "TYPE_TV_EPISODE";
+
+        /**
+         * The program type for clip.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_CLIP = "TYPE_CLIP";
+
+        /**
+         * The program type for event.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_EVENT = "TYPE_EVENT";
+
+        /**
+         * The program type for channel.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_CHANNEL = "TYPE_CHANNEL";
+
+        /**
+         * The program type for track.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_TRACK = "TYPE_TRACK";
+
+        /**
+         * The program type for album.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_ALBUM = "TYPE_ALBUM";
+
+        /**
+         * The program type for artist.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_ARTIST = "TYPE_ARTIST";
+
+        /**
+         * The program type for playlist.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_PLAYLIST = "TYPE_PLAYLIST";
+
+        /**
+         * The program type for station.
+         *
+         * @see #COLUMN_TYPE
+         */
+        public static final String TYPE_STATION = "TYPE_STATION";
+
+        /**
+         * The watch next type for CONTINUE.
+         *
+         * @see #COLUMN_WATCH_NEXT_TYPE
+         */
+        public static final String WATCH_NEXT_TYPE_CONTINUE = "WATCH_NEXT_TYPE_CONTINUE";
+
+        /**
+         * The watch next type for NEXT.
+         *
+         * @see #COLUMN_WATCH_NEXT_TYPE
+         */
+        public static final String WATCH_NEXT_TYPE_NEXT = "WATCH_NEXT_TYPE_NEXT";
+
+        /**
+         * The watch next type for NEW.
+         *
+         * @see #COLUMN_WATCH_NEXT_TYPE
+         */
+        public static final String WATCH_NEXT_TYPE_NEW = "WATCH_NEXT_TYPE_NEW";
+
+        /**
+         * The aspect ratio for 16:9.
+         *
+         * @see #COLUMN_POSTER_ART_ASPECT_RATIO
+         * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
+         */
+        public static final String ASPECT_RATIO_16_9 = "ASPECT_RATIO_16_9";
+
+        /**
+         * The aspect ratio for 3:2.
+         *
+         * @see #COLUMN_POSTER_ART_ASPECT_RATIO
+         * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
+         */
+        public static final String ASPECT_RATIO_3_2 = "ASPECT_RATIO_3_2";
+
+        /**
+         * The aspect ratio for 1:1.
+         *
+         * @see #COLUMN_POSTER_ART_ASPECT_RATIO
+         * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
+         */
+        public static final String ASPECT_RATIO_1_1 = "ASPECT_RATIO_1_1";
+
+        /**
+         * The aspect ratio for 2:3.
+         *
+         * @see #COLUMN_POSTER_ART_ASPECT_RATIO
+         * @see #COLUMN_THUMBNAIL_ASPECT_RATIO
+         */
+        public static final String ASPECT_RATIO_2_3 = "ASPECT_RATIO_2_3";
+
+        /**
+         * The availability for "available to this user".
+         *
+         * @see #COLUMN_AVAILABILITY
+         */
+        public static final String AVAILABILITY_AVAILABLE = "AVAILABILITY_AVAILABLE";
+
+        /**
+         * The availability for "free with subscription".
+         *
+         * @see #COLUMN_AVAILABILITY
+         */
+        public static final String AVAILABILITY_FREE_WITH_SUBSCRIPTION =
+                "AVAILABILITY_FREE_WITH_SUBSCRIPTION";
+
+        /**
+         * The availability for "paid content, either to-own or rental
+         * (user has not purchased/rented).
+         *
+         * @see #COLUMN_AVAILABILITY
+         */
+        public static final String AVAILABILITY_PAID_CONTENT = "AVAILABILITY_PAID_CONTENT";
+
+        /**
+         * The interaction type for "listens".
+         *
+         * @see #COLUMN_INTERACTION_TYPE
+         */
+        public static final String INTERACTION_TYPE_LISTENS = "INTERACTION_TYPE_LISTENS";
+
+        /**
+         * The interaction type for "followers".
+         *
+         * @see #COLUMN_INTERACTION_TYPE
+         */
+        public static final String INTERACTION_TYPE_FOLLOWERS = "INTERACTION_TYPE_FOLLOWERS";
+
+        /**
+         * The interaction type for "fans".
+         *
+         * @see #COLUMN_INTERACTION_TYPE
+         */
+        public static final String INTERACTION_TYPE_FANS = "INTERACTION_TYPE_FANS";
+
+        /**
+         * The interaction type for "likes".
+         *
+         * @see #COLUMN_INTERACTION_TYPE
+         */
+        public static final String INTERACTION_TYPE_LIKES = "INTERACTION_TYPE_LIKES";
+
+        /**
+         * The interaction type for "thumbs".
+         *
+         * @see #COLUMN_INTERACTION_TYPE
+         */
+        public static final String INTERACTION_TYPE_THUMBS = "INTERACTION_TYPE_THUMBS";
+
+        /**
+         * The interaction type for "views".
+         *
+         * @see #COLUMN_INTERACTION_TYPE
+         */
+        public static final String INTERACTION_TYPE_VIEWS = "INTERACTION_TYPE_VIEWS";
+
+        /**
+         * The interaction type for "viewers".
+         *
+         * @see #COLUMN_INTERACTION_TYPE
+         */
+        public static final String INTERACTION_TYPE_VIEWERS = "INTERACTION_TYPE_VIEWERS";
+
+        /**
+         * The review rating style for five star rating.
+         *
+         * @see #COLUMN_REVIEW_RATING_STYLE
+         */
+        public static final String REVIEW_RATING_STYLE_STARS = "REVIEW_RATING_STYLE_STARS";
+
+        /**
+         * The review rating style for thumbs-up and thumbs-down rating.
+         *
+         * @see #COLUMN_REVIEW_RATING_STYLE
+         */
+        public static final String REVIEW_RATING_STYLE_THUMBS_UP_DOWN =
+                "REVIEW_RATING_STYLE_THUMBS_UP_DOWN";
+
+        /**
+         * The review rating style for 0 to 100 point system.
+         *
+         * @see #COLUMN_REVIEW_RATING_STYLE
+         */
+        public static final String REVIEW_RATING_STYLE_PERCENTAGE =
+                "REVIEW_RATING_STYLE_PERCENTAGE";
+
+        /**
          * The ID of the TV channel that provides this TV program.
          *
          * <p>This is a part of the channel URI and matches to {@link BaseColumns#_ID}.
@@ -1099,6 +1331,44 @@
         public static final String COLUMN_CHANNEL_ID = "channel_id";
 
         /**
+         * The type of this program content.
+         *
+         * <p>The value should match one of the followings:
+         * {@link #TYPE_MOVIE},
+         * {@link #TYPE_TV_SERIES},
+         * {@link #TYPE_TV_SEASON},
+         * {@link #TYPE_TV_EPISODE},
+         * {@link #TYPE_CLIP},
+         * {@link #TYPE_EVENT},
+         * {@link #TYPE_CHANNEL},
+         * {@link #TYPE_TRACK},
+         * {@link #TYPE_ALBUM},
+         * {@link #TYPE_ARTIST},
+         * {@link #TYPE_PLAYLIST}, and
+         * {@link #TYPE_STATION}.
+         *
+         * <p>This is a required field if the program is from a {@link Channels#TYPE_PREVIEW}
+         * channel.
+         *
+         * <p>Type: TEXT
+         */
+        public static final String COLUMN_TYPE = "type";
+
+        /**
+         * The "watch next" type of this program content.
+         *
+         * <p>The value should match one of the followings:
+         * {@link #WATCH_NEXT_TYPE_CONTINUE},
+         * {@link #WATCH_NEXT_TYPE_NEXT}, and
+         * {@link #WATCH_NEXT_TYPE_NEW}.
+         *
+         * <p>Can be empty.
+         *
+         * <p>Type: TEXT
+         */
+        public static final String COLUMN_WATCH_NEXT_TYPE = "watch_next_type";
+
+        /**
          * The title of this TV program.
          *
          * <p>If this program is an episodic TV show, it is recommended that the title is the series
@@ -1329,6 +1599,19 @@
         public static final String COLUMN_POSTER_ART_URI = "poster_art_uri";
 
         /**
+         * The aspect ratio of the poster art for this TV program.
+         *
+         * <p>The value should match one of the followings:
+         * {@link #ASPECT_RATIO_16_9},
+         * {@link #ASPECT_RATIO_3_2},
+         * {@link #ASPECT_RATIO_1_1}, and
+         * {@link #ASPECT_RATIO_2_3}.
+         *
+         * <p>Type: TEXT
+         */
+        public static final String COLUMN_POSTER_ART_ASPECT_RATIO = "poster_art_aspect_ratio";
+
+        /**
          * The URI for the thumbnail of this TV program.
          *
          * <p>The system can generate a thumbnail from the poster art if this column is not
@@ -1351,6 +1634,104 @@
         public static final String COLUMN_THUMBNAIL_URI = "thumbnail_uri";
 
         /**
+         * The aspect ratio of the thumbnail for this TV program.
+         *
+         * <p>The value should match one of the followings:
+         * {@link #ASPECT_RATIO_16_9},
+         * {@link #ASPECT_RATIO_3_2},
+         * {@link #ASPECT_RATIO_1_1}, and
+         * {@link #ASPECT_RATIO_2_3}.
+         *
+         * <p>Type: TEXT
+         */
+        public static final String COLUMN_THUMBNAIL_ASPECT_RATIO = "poster_thumbnail_aspect_ratio";
+
+        /**
+         * The URI for the logo of this TV program.
+         *
+         * <p>This is a small badge shown on top of the poster art or thumbnail representing the
+         * source of the content.
+         *
+         * <p>The data in the column must be a URL, or a URI in one of the following formats:
+         *
+         * <ul>
+         * <li>content ({@link android.content.ContentResolver#SCHEME_CONTENT})</li>
+         * <li>android.resource ({@link android.content.ContentResolver#SCHEME_ANDROID_RESOURCE})
+         * </li>
+         * <li>file ({@link android.content.ContentResolver#SCHEME_FILE})</li>
+         * </ul>
+         *
+         * <p>Can be empty.
+         *
+         * <p>Type: TEXT
+         */
+        public static final String COLUMN_LOGO = "logo";
+
+        /**
+         * The availability of this TV program.
+         *
+         * <p>The value should match one of the followings:
+         * {@link #AVAILABILITY_AVAILABLE},
+         * {@link #AVAILABILITY_FREE_WITH_SUBSCRIPTION}, and
+         * {@link #AVAILABILITY_PAID_CONTENT}.
+         *
+         * <p>Type: TEXT
+         */
+        public static final String COLUMN_AVAILABILITY = "availability";
+
+        /**
+         * The starting price of this TV program.
+         *
+         * <p>This indicates the lowest regular acquisition cost of the content. It is only used
+         * if the availability of the program is {@link #AVAILABILITY_PAID_CONTENT}.
+         *
+         * <p>Type: TEXT
+         * @see #COLUMN_OFFER_PRICE
+         */
+        public static final String COLUMN_STARTING_PRICE = "starting_price";
+
+        /**
+         * The offer price of this TV program.
+         *
+         * <p>This is the promotional cost of the content. It is only used if the availability of
+         * the program is {@link #AVAILABILITY_PAID_CONTENT}.
+         *
+         * <p>Type: TEXT
+         * @see #COLUMN_STARTING_PRICE
+         */
+        public static final String COLUMN_OFFER_PRICE = "offer_price";
+
+        /**
+         * The release date of this TV program.
+         *
+         * <p>The value should be in the form of either "yyyy-MM-dd" or "yyyy".
+         *
+         * <p>Type: TEXT
+         */
+        public static final String COLUMN_RELEASE_DATE = "release_date";
+
+        /**
+         * The count of the items included in this TV program.
+         *
+         * <p>This is only relevant if the program represents a collection of items such as series,
+         * episodes, or music tracks.
+         *
+         * <p>Type: INTEGER
+         */
+        public static final String COLUMN_ITEM_COUNT = "item_count";
+
+        /**
+         * The flag indicating whether this TV program is live or not.
+         *
+         * <p>A value of 1 indicates that the content is airing and should be consumed now, a value
+         * of 0 indicates that the content is off the air and does not need to be consumed at the
+         * present time. If not specified, the value is set to 0 (not live) by default.
+         *
+         * <p>Type: INTEGER (boolean)
+         */
+        public static final String COLUMN_LIVE = "live";
+
+        /**
          * The flag indicating whether this TV program is searchable or not.
          *
          * <p>The columns of searchable programs can be read by other applications that have proper
@@ -1535,6 +1916,67 @@
         @SystemApi
         public static final String COLUMN_TRANSIENT = "transient";
 
+        /**
+         * The type of interaction for this TV program.
+         *
+         * <p> The value should match one of the followings:
+         * {@link #INTERACTION_TYPE_LISTENS},
+         * {@link #INTERACTION_TYPE_FOLLOWERS},
+         * {@link #INTERACTION_TYPE_FANS},
+         * {@link #INTERACTION_TYPE_LIKES},
+         * {@link #INTERACTION_TYPE_THUMBS},
+         * {@link #INTERACTION_TYPE_VIEWS}, and
+         * {@link #INTERACTION_TYPE_VIEWERS}.
+         *
+         * <p>Type: TEXT
+         * @see #COLUMN_INTERACTION_COUNT
+         */
+        public static final String COLUMN_INTERACTION_TYPE = "interaction_type";
+
+        /**
+         * The interaction count for this program.
+         *
+         * <p>This indicates the number of times interaction has happened.
+         *
+         * <p>Type: INTEGER
+         * @see #COLUMN_INTERACTION_TYPE
+         */
+        public static final String COLUMN_INTERACTION_COUNT = "interaction_count";
+
+        /**
+         * The author or artist of this content.
+         *
+         * <p>Type: TEXT
+         */
+        public static final String COLUMN_AUTHOR = "author";
+
+        /**
+         * The review rating score style used for {@link #COLUMN_REVIEW_RATING}.
+         *
+         * <p> The value should match one of the followings: {@link #REVIEW_RATING_STYLE_STARS},
+         * {@link #REVIEW_RATING_STYLE_THUMBS_UP_DOWN}, and {@link #REVIEW_RATING_STYLE_PERCENTAGE}.
+         *
+         * <p>Type: TEXT
+         * @see #COLUMN_REVIEW_RATING
+         */
+        public static final String COLUMN_REVIEW_RATING_STYLE = "review_rating_style";
+
+        /**
+         * The review rating score for this program.
+         *
+         * <p>The format of the value is dependent on {@link #COLUMN_REVIEW_RATING_STYLE}. If the
+         * style is {@link #REVIEW_RATING_STYLE_STARS}, the value should be a real number between
+         * 0.0 and 5.0. (e.g. "4.5") If the style is {@link #REVIEW_RATING_STYLE_THUMBS_UP_DOWN},
+         * the value should be two integers, one for thumbs-up count and the other for thumbs-down
+         * count, with a comma between them. (e.g. "200,40") If the style is
+         * {@link #REVIEW_RATING_STYLE_PERCENTAGE}, the value shoule be a real number between 0 and
+         * 100. (e.g. "99.9")
+         *
+         * <p>Type: TEXT
+         * @see #COLUMN_REVIEW_RATING_STYLE
+         */
+        public static final String COLUMN_REVIEW_RATING = "review_rating";
+
         private Programs() {}
 
         /** Canonical genres for TV programs. */
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 1eae8db..b630270 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -324,6 +324,24 @@
     public static final String ACTION_VIEW_RECORDING_SCHEDULES =
             "android.media.tv.action.VIEW_RECORDING_SCHEDULES";
 
+    /**
+     * Action sent by an application telling the system to set the given channel as browsable.
+     *
+     * <p>The intent must contain the following bundle parameters:
+     * <ul>
+     *     <li>{@link #EXTRA_CHANNEL_ID} then channel ID as an integer.
+     *     <li>{@link #EXTRA_PACKAGE_NAME} the package name of the requesting application.
+     * </ul>
+     */
+    public static final String ACTION_MAKE_CHANNEL_BROWSABLE
+            = "android.media.tv.action.MAKE_CHANNEL_BROWSABLE";
+
+    /** The key for a bundle parameter containing a channel ID as an integer */
+    public static final String EXTRA_CHANNEL_ID = "android.media.tv.extra.CHANNEL_ID";
+
+    /** The key for a bundle parameter containing a package name as a string. */
+    public static final String EXTRA_PACKAGE_NAME = "android.media.tv.extra.PACKAGE_NAME";
+
     private final ITvInputManager mService;
 
     private final Object mLock = new Object();
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 8d4271f..f69313c 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -11,6 +11,7 @@
     android_media_MediaDrm.cpp \
     android_media_MediaExtractor.cpp \
     android_media_MediaHTTPConnection.cpp \
+    android_media_MediaMetricsJNI.cpp \
     android_media_MediaMetadataRetriever.cpp \
     android_media_MediaMuxer.cpp \
     android_media_MediaPlayer.cpp \
diff --git a/media/jni/android_media_BufferingParams.h b/media/jni/android_media_BufferingParams.h
new file mode 100644
index 0000000..24c51f5
--- /dev/null
+++ b/media/jni/android_media_BufferingParams.h
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+#ifndef _ANDROID_MEDIA_BUFFERING_PARAMS_H_
+#define _ANDROID_MEDIA_BUFFERING_PARAMS_H_
+
+#include <media/BufferingSettings.h>
+
+namespace android {
+
+// This entire class is inline
+struct BufferingParams {
+    BufferingSettings settings;
+
+    struct fields_t {
+        jclass      clazz;
+        jmethodID   constructID;
+
+        jfieldID    initial_buffering_mode;
+        jfieldID    rebuffering_mode;
+        jfieldID    initial_watermark_ms;
+        jfieldID    initial_watermark_kb;
+        jfieldID    rebuffering_watermark_low_ms;
+        jfieldID    rebuffering_watermark_high_ms;
+        jfieldID    rebuffering_watermark_low_kb;
+        jfieldID    rebuffering_watermark_high_kb;
+
+        void init(JNIEnv *env) {
+            jclass lclazz = env->FindClass("android/media/BufferingParams");
+            if (lclazz == NULL) {
+                return;
+            }
+
+            clazz = (jclass)env->NewGlobalRef(lclazz);
+            if (clazz == NULL) {
+                return;
+            }
+
+            constructID = env->GetMethodID(clazz, "<init>", "()V");
+
+            initial_buffering_mode = env->GetFieldID(clazz, "mInitialBufferingMode", "I");
+            rebuffering_mode = env->GetFieldID(clazz, "mRebufferingMode", "I");
+            initial_watermark_ms = env->GetFieldID(clazz, "mInitialWatermarkMs", "I");
+            initial_watermark_kb = env->GetFieldID(clazz, "mInitialWatermarkKB", "I");
+            rebuffering_watermark_low_ms = env->GetFieldID(clazz, "mRebufferingWatermarkLowMs", "I");
+            rebuffering_watermark_high_ms = env->GetFieldID(clazz, "mRebufferingWatermarkHighMs", "I");
+            rebuffering_watermark_low_kb = env->GetFieldID(clazz, "mRebufferingWatermarkLowKB", "I");
+            rebuffering_watermark_high_kb = env->GetFieldID(clazz, "mRebufferingWatermarkHighKB", "I");
+
+            env->DeleteLocalRef(lclazz);
+        }
+
+        void exit(JNIEnv *env) {
+            env->DeleteGlobalRef(clazz);
+            clazz = NULL;
+        }
+    };
+
+    void fillFromJobject(JNIEnv *env, const fields_t& fields, jobject params) {
+        settings.mInitialBufferingMode =
+            (BufferingMode)env->GetIntField(params, fields.initial_buffering_mode);
+        settings.mRebufferingMode =
+            (BufferingMode)env->GetIntField(params, fields.rebuffering_mode);
+        settings.mInitialWatermarkMs =
+            env->GetIntField(params, fields.initial_watermark_ms);
+        settings.mInitialWatermarkKB =
+            env->GetIntField(params, fields.initial_watermark_kb);
+        settings.mRebufferingWatermarkLowMs =
+            env->GetIntField(params, fields.rebuffering_watermark_low_ms);
+        settings.mRebufferingWatermarkHighMs =
+            env->GetIntField(params, fields.rebuffering_watermark_high_ms);
+        settings.mRebufferingWatermarkLowKB =
+            env->GetIntField(params, fields.rebuffering_watermark_low_kb);
+        settings.mRebufferingWatermarkHighKB =
+            env->GetIntField(params, fields.rebuffering_watermark_high_kb);
+    }
+
+    jobject asJobject(JNIEnv *env, const fields_t& fields) {
+        jobject params = env->NewObject(fields.clazz, fields.constructID);
+        if (params == NULL) {
+            return NULL;
+        }
+        env->SetIntField(params, fields.initial_buffering_mode, (jint)settings.mInitialBufferingMode);
+        env->SetIntField(params, fields.rebuffering_mode, (jint)settings.mRebufferingMode);
+        env->SetIntField(params, fields.initial_watermark_ms, (jint)settings.mInitialWatermarkMs);
+        env->SetIntField(params, fields.initial_watermark_kb, (jint)settings.mInitialWatermarkKB);
+        env->SetIntField(params, fields.rebuffering_watermark_low_ms, (jint)settings.mRebufferingWatermarkLowMs);
+        env->SetIntField(params, fields.rebuffering_watermark_high_ms, (jint)settings.mRebufferingWatermarkHighMs);
+        env->SetIntField(params, fields.rebuffering_watermark_low_kb, (jint)settings.mRebufferingWatermarkLowKB);
+        env->SetIntField(params, fields.rebuffering_watermark_high_kb, (jint)settings.mRebufferingWatermarkHighKB);
+
+        return params;
+    }
+};
+
+}  // namespace android
+
+#endif  // _ANDROID_MEDIA_BUFFERING_PARAMS_H_
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index c2c66fd..6f9883c 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -21,6 +21,7 @@
 #include "android_media_MediaCodec.h"
 
 #include "android_media_MediaCrypto.h"
+#include "android_media_MediaMetricsJNI.h"
 #include "android_media_Utils.h"
 #include "android_runtime/AndroidRuntime.h"
 #include "android_runtime/android_view_Surface.h"
@@ -618,6 +619,12 @@
     return OK;
 }
 
+status_t JMediaCodec::getMetrics(JNIEnv *, Parcel *reply) const {
+
+    status_t status = mCodec->getMetrics(reply);
+    return status;
+}
+
 status_t JMediaCodec::setParameters(const sp<AMessage> &msg) {
     return mCodec->setParameters(msg);
 }
@@ -1646,6 +1653,37 @@
     return NULL;
 }
 
+static jobject
+android_media_MediaCodec_getMetrics(JNIEnv *env, jobject thiz)
+{
+    ALOGV("android_media_MediaCodec_getMetrics");
+
+    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
+    if (codec == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return 0;
+    }
+
+    // get what we have for the metrics from the codec
+    Parcel reply;
+    status_t err = codec->getMetrics(env, &reply);
+    if (err != OK) {
+        ALOGE("getMetrics failed");
+        return (jobject) NULL;
+    }
+
+    // build and return the Bundle
+    MediaAnalyticsItem *item = new MediaAnalyticsItem;
+    item->readFromParcel(reply);
+    jobject mybundle = MediaMetricsJNI::writeMetricsToBundle(env, item, NULL);
+
+    // housekeeping
+    delete item;
+    item = NULL;
+
+    return mybundle;
+}
+
 static void android_media_MediaCodec_setParameters(
         JNIEnv *env, jobject thiz, jobjectArray keys, jobjectArray vals) {
     ALOGV("android_media_MediaCodec_setParameters");
@@ -1954,6 +1992,9 @@
     { "getName", "()Ljava/lang/String;",
       (void *)android_media_MediaCodec_getName },
 
+    { "getMetrics", "()Landroid/os/Bundle;",
+      (void *)android_media_MediaCodec_getMetrics},
+
     { "setParameters", "([Ljava/lang/String;[Ljava/lang/Object;)V",
       (void *)android_media_MediaCodec_setParameters },
 
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index 5f0d3df..b3b1b3a 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -111,6 +111,8 @@
 
     status_t getName(JNIEnv *env, jstring *name) const;
 
+    status_t getMetrics(JNIEnv *env, Parcel *reply) const;
+
     status_t setParameters(const sp<AMessage> &params);
 
     void setVideoScalingMode(int mode);
diff --git a/media/jni/android_media_MediaMetricsJNI.cpp b/media/jni/android_media_MediaMetricsJNI.cpp
new file mode 100644
index 0000000..fb606ba
--- /dev/null
+++ b/media/jni/android_media_MediaMetricsJNI.cpp
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+#include <android_runtime/AndroidRuntime.h>
+#include <jni.h>
+#include <JNIHelp.h>
+
+#include "android_media_MediaMetricsJNI.h"
+#include <media/MediaAnalyticsItem.h>
+
+
+namespace android {
+
+// place the attributes into a java Bundle object
+// decide whether this is appropriately scoped here.
+// if we do it somewhere else, we have to figure a "give me all the attrs"
+// access to the inside of MediaAnalyticsItem
+jobject MediaMetricsJNI::writeMetricsToBundle(JNIEnv* env, MediaAnalyticsItem *item, jobject mybundle) {
+
+    jclass clazzBundle = env->FindClass("android/os/Bundle");
+    if (clazzBundle==NULL) {
+        ALOGD("can't find android/os/Bundle");
+        return NULL;
+    }
+    // sometimes the caller provides one for us to fill
+    if (mybundle == NULL) {
+        // create the bundle
+        jmethodID constructID = env->GetMethodID(clazzBundle, "<init>", "()V");
+        mybundle = env->NewObject(clazzBundle, constructID);
+        if (mybundle == NULL) {
+            return NULL;
+        }
+    }
+
+    // grab methods that we can invoke
+    jmethodID setIntID = env->GetMethodID(clazzBundle, "putInt", "(Ljava/lang/String;I)V");
+    jmethodID setLongID = env->GetMethodID(clazzBundle, "putLong", "(Ljava/lang/String;J)V");
+    jmethodID setDoubleID = env->GetMethodID(clazzBundle, "putDouble", "(Ljava/lang/String;D)V");
+    jmethodID setStringID = env->GetMethodID(clazzBundle, "putString", "(Ljava/lang/String;Ljava/lang/String;)V");
+
+    // env, class, method, {parms}
+    //env->CallVoidMethod(env, mybundle, setIntID, jstr, jint);
+
+    // iterate through my attributes
+    // -- get name, get type, get value
+    // -- insert appropriately into the bundle
+    for (size_t i = 0 ; i < item->mPropCount; i++ ) {
+	    MediaAnalyticsItem::Prop *prop = &item->mProps[i];
+            // build the key parameter from prop->mName
+            jstring keyName = env->NewStringUTF(prop->mName);
+            // invoke the appropriate method to insert
+            switch (prop->mType) {
+                case MediaAnalyticsItem::kTypeInt32:
+                    env->CallVoidMethod(mybundle, setIntID,
+                                        keyName, (jint) prop->u.int32Value);
+                    break;
+                case MediaAnalyticsItem::kTypeInt64:
+                    env->CallVoidMethod(mybundle, setLongID,
+                                        keyName, (jlong) prop->u.int64Value);
+                    break;
+                case MediaAnalyticsItem::kTypeDouble:
+                    env->CallVoidMethod(mybundle, setDoubleID,
+                                        keyName, (jdouble) prop->u.doubleValue);
+                    break;
+                case MediaAnalyticsItem::kTypeCString:
+                    env->CallVoidMethod(mybundle, setStringID, keyName,
+                                        env->NewStringUTF(prop->u.CStringValue));
+                    break;
+                default:
+                        ALOGE("to_String bad item type: %d for %s",
+                              prop->mType, prop->mName);
+                        break;
+            }
+    }
+
+    return mybundle;
+}
+
+};  // namespace android
+
diff --git a/media/jni/android_media_MediaMetricsJNI.h b/media/jni/android_media_MediaMetricsJNI.h
new file mode 100644
index 0000000..d174212
--- /dev/null
+++ b/media/jni/android_media_MediaMetricsJNI.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#ifndef _ANDROID_MEDIA_MEDIAMETRICSJNI_H_
+#define _ANDROID_MEDIA_MEDIAMETRICSJNI_H_
+
+#include <android_runtime/AndroidRuntime.h>
+#include <jni.h>
+#include <JNIHelp.h>
+#include <media/MediaAnalyticsItem.h>
+
+namespace android {
+
+class MediaMetricsJNI {
+public:
+    static jobject writeMetricsToBundle(JNIEnv* env, MediaAnalyticsItem *item, jobject mybundle);
+};
+
+};  // namespace android
+
+#endif //  _ANDROID_MEDIA_MEDIAMETRICSJNI_H_
diff --git a/media/jni/android_media_MediaMuxer.cpp b/media/jni/android_media_MediaMuxer.cpp
index 216624e..c3461f0 100644
--- a/media/jni/android_media_MediaMuxer.cpp
+++ b/media/jni/android_media_MediaMuxer.cpp
@@ -23,6 +23,9 @@
 #include "jni.h"
 #include "JNIHelp.h"
 
+#include <unistd.h>
+#include <fcntl.h>
+
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -138,6 +141,28 @@
     int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
     ALOGV("native_setup: fd %d", fd);
 
+    // It appears that if an invalid file descriptor is passed through
+    // binder calls, the server-side of the inter-process function call
+    // is skipped. As a result, the check at the server-side to catch
+    // the invalid file descritpor never gets invoked. This is to workaround
+    // this issue by checking the file descriptor first before passing
+    // it through binder call.
+    int flags = fcntl(fd, F_GETFL);
+    if (flags == -1) {
+        ALOGE("Fail to get File Status Flags err: %s", strerror(errno));
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                "Invalid file descriptor");
+        return 0;
+    }
+
+    // fd must be in read-write mode or write-only mode.
+    if ((flags & (O_RDWR | O_WRONLY)) == 0) {
+        ALOGE("File descriptor is not in read-write mode or write-only mode");
+        jniThrowException(env, "java/io/IOException",
+                "File descriptor is not in read-write mode or write-only mode");
+        return 0;
+    }
+
     MediaMuxer::OutputFormat fileFormat =
         static_cast<MediaMuxer::OutputFormat>(format);
     sp<MediaMuxer> muxer = new MediaMuxer(fd, fileFormat);
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index c52ed94..5e8135f 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -23,6 +23,8 @@
 #include <media/AudioResamplerPublic.h>
 #include <media/IMediaHTTPService.h>
 #include <media/MediaPlayerInterface.h>
+#include <media/MediaAnalyticsItem.h>
+#include <media/stagefright/Utils.h>            // for FOURCC definition
 #include <stdio.h>
 #include <assert.h>
 #include <limits.h>
@@ -37,7 +39,9 @@
 #include "utils/Errors.h"  // for status_t
 #include "utils/KeyedVector.h"
 #include "utils/String8.h"
+#include "android_media_BufferingParams.h"
 #include "android_media_MediaDataSource.h"
+#include "android_media_MediaMetricsJNI.h"
 #include "android_media_PlaybackParams.h"
 #include "android_media_SyncParams.h"
 #include "android_media_Utils.h"
@@ -51,6 +55,90 @@
 #include <binder/IServiceManager.h>
 
 #include "android_util_Binder.h"
+
+// Modular DRM begin
+#include <media/drm/DrmAPI.h>
+
+#define FIND_CLASS(var, className) \
+var = env->FindClass(className); \
+LOG_FATAL_IF(! (var), "Unable to find class " className);
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
+
+#define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \
+var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \
+LOG_FATAL_IF(! (var), "Unable to find method " fieldName);
+
+#define GET_STATIC_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+var = env->GetStaticFieldID(clazz, fieldName, fieldDescriptor); \
+LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
+
+
+// TODO: investigate if these can be shared with their MediaDrm counterparts
+struct RequestFields {
+    jfieldID data;
+    jfieldID defaultUrl;
+    jfieldID requestType;
+};
+
+struct HashmapFields {
+    jmethodID init;
+    jmethodID get;
+    jmethodID put;
+    jmethodID entrySet;
+};
+
+struct SetFields {
+    jmethodID iterator;
+};
+
+struct IteratorFields {
+    jmethodID next;
+    jmethodID hasNext;
+};
+
+struct EntryFields {
+    jmethodID getKey;
+    jmethodID getValue;
+};
+
+struct KeyTypes {
+    jint kKeyTypeStreaming;
+    jint kKeyTypeOffline;
+    jint kKeyTypeRelease;
+};
+
+static KeyTypes gKeyTypes;
+
+struct KeyRequestTypes {
+    jint kKeyRequestTypeInitial;
+    jint kKeyRequestTypeRenewal;
+    jint kKeyRequestTypeRelease;
+};
+
+static KeyRequestTypes gKeyRequestTypes;
+
+struct StateExceptionFields {
+    jmethodID init;
+    jclass classId;
+};
+
+struct drm_fields_t {
+    RequestFields keyRequest;
+    HashmapFields hashmap;
+    SetFields set;
+    IteratorFields iterator;
+    EntryFields entry;
+    StateExceptionFields stateException;
+    jclass stringClassId;
+};
+
+static drm_fields_t gFields;
+
+// Modular DRM end
+
 // ----------------------------------------------------------------------------
 
 using namespace android;
@@ -69,6 +157,7 @@
 };
 static fields_t fields;
 
+static BufferingParams::fields_t gBufferingParamsFields;
 static PlaybackParams::fields_t gPlaybackParamsFields;
 static SyncParams::fields_t gSyncParamsFields;
 
@@ -343,6 +432,66 @@
     setVideoSurface(env, thiz, jsurface, true /* mediaPlayerMustBeAlive */);
 }
 
+static jobject
+android_media_MediaPlayer_getDefaultBufferingParams(JNIEnv *env, jobject thiz)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return NULL;
+    }
+
+    BufferingParams bp;
+    BufferingSettings &settings = bp.settings;
+    process_media_player_call(
+            env, thiz, mp->getDefaultBufferingSettings(&settings),
+            "java/lang/IllegalStateException", "unexpected error");
+    ALOGV("getDefaultBufferingSettings:{%s}", settings.toString().string());
+
+    return bp.asJobject(env, gBufferingParamsFields);
+}
+
+static jobject
+android_media_MediaPlayer_getBufferingParams(JNIEnv *env, jobject thiz)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return NULL;
+    }
+
+    BufferingParams bp;
+    BufferingSettings &settings = bp.settings;
+    process_media_player_call(
+            env, thiz, mp->getBufferingSettings(&settings),
+            "java/lang/IllegalStateException", "unexpected error");
+    ALOGV("getBufferingSettings:{%s}", settings.toString().string());
+
+    return bp.asJobject(env, gBufferingParamsFields);
+}
+
+static void
+android_media_MediaPlayer_setBufferingParams(JNIEnv *env, jobject thiz, jobject params)
+{
+    if (params == NULL) {
+        return;
+    }
+
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+
+    BufferingParams bp;
+    bp.fillFromJobject(env, gBufferingParamsFields, params);
+    ALOGV("setBufferingParams:{%s}", bp.settings.toString().string());
+
+    process_media_player_call(
+            env, thiz, mp->setBufferingSettings(bp.settings),
+            "java/lang/IllegalStateException", "unexpected error");
+}
+
 static void
 android_media_MediaPlayer_prepare(JNIEnv *env, jobject thiz)
 {
@@ -622,6 +771,33 @@
     return (jint) h;
 }
 
+static jobject
+android_media_MediaPlayer_getMetrics(JNIEnv *env, jobject thiz)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return 0;
+    }
+
+    Parcel p;
+    int key = FOURCC('m','t','r','X');
+    status_t status = mp->getParameter(key, &p);
+    if (status != OK) {
+        ALOGD("getMetrics() failed: %d", status);
+        return (jobject) NULL;
+    }
+
+    MediaAnalyticsItem *item = new MediaAnalyticsItem;
+    item->readFromParcel(p);
+    jobject mybundle = MediaMetricsJNI::writeMetricsToBundle(env, item, NULL);
+
+    // housekeeping
+    delete item;
+    item = NULL;
+
+    return mybundle;
+}
 
 static jint
 android_media_MediaPlayer_getCurrentPosition(JNIEnv *env, jobject thiz)
@@ -860,6 +1036,56 @@
 
     env->DeleteLocalRef(clazz);
 
+    gBufferingParamsFields.init(env);
+
+    // Modular DRM
+    FIND_CLASS(clazz, "android/media/MediaDrm");
+    if (clazz) {
+        jfieldID field;
+        GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_STREAMING", "I");
+        gKeyTypes.kKeyTypeStreaming = env->GetStaticIntField(clazz, field);
+        GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_OFFLINE", "I");
+        gKeyTypes.kKeyTypeOffline = env->GetStaticIntField(clazz, field);
+        GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I");
+        gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field);
+
+        env->DeleteLocalRef(clazz);
+    } else {
+        ALOGE("JNI getKeyRequest android_media_MediaPlayer_native_init couldn't "
+              "get clazz android/media/MediaDrm");
+    }
+
+    FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
+    if (clazz) {
+        GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
+        GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
+        GET_FIELD_ID(gFields.keyRequest.requestType, clazz, "mRequestType", "I");
+
+        jfieldID field;
+        GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_INITIAL", "I");
+        gKeyRequestTypes.kKeyRequestTypeInitial = env->GetStaticIntField(clazz, field);
+        GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RENEWAL", "I");
+        gKeyRequestTypes.kKeyRequestTypeRenewal = env->GetStaticIntField(clazz, field);
+        GET_STATIC_FIELD_ID(field, clazz, "REQUEST_TYPE_RELEASE", "I");
+        gKeyRequestTypes.kKeyRequestTypeRelease = env->GetStaticIntField(clazz, field);
+
+        env->DeleteLocalRef(clazz);
+    } else {
+        ALOGE("JNI getKeyRequest android_media_MediaPlayer_native_init couldn't "
+              "get clazz android/media/MediaDrm$KeyRequest");
+    }
+
+    FIND_CLASS(clazz, "android/media/MediaDrm$MediaDrmStateException");
+    if (clazz) {
+        GET_METHOD_ID(gFields.stateException.init, clazz, "<init>", "(ILjava/lang/String;)V");
+        gFields.stateException.classId = static_cast<jclass>(env->NewGlobalRef(clazz));
+
+        env->DeleteLocalRef(clazz);
+    } else {
+        ALOGE("JNI getKeyRequest android_media_MediaPlayer_native_init couldn't "
+              "get clazz android/media/MediaDrm$MediaDrmStateException");
+    }
+
     gPlaybackParamsFields.init(env);
     gSyncParamsFields.init(env);
 }
@@ -1033,6 +1259,441 @@
     ;
 }
 
+/////////////////////////////////////////////////////////////////////////////////////
+// Modular DRM begin
+
+// TODO: investigate if these can be shared with their MediaDrm counterparts
+static void throwDrmStateException(JNIEnv *env, const char *msg, status_t err)
+{
+    ALOGE("Illegal DRM state exception: %s (%d)", msg, err);
+
+    jobject exception = env->NewObject(gFields.stateException.classId,
+            gFields.stateException.init, static_cast<int>(err),
+            env->NewStringUTF(msg));
+    env->Throw(static_cast<jthrowable>(exception));
+}
+
+// TODO: investigate if these can be shared with their MediaDrm counterparts
+static bool throwDrmExceptionAsNecessary(JNIEnv *env, status_t err, const char *msg = NULL)
+{
+    const char *drmMessage = "Unknown DRM Msg";
+
+    switch (err) {
+    case ERROR_DRM_UNKNOWN:
+        drmMessage = "General DRM error";
+        break;
+    case ERROR_DRM_NO_LICENSE:
+        drmMessage = "No license";
+        break;
+    case ERROR_DRM_LICENSE_EXPIRED:
+        drmMessage = "License expired";
+        break;
+    case ERROR_DRM_SESSION_NOT_OPENED:
+        drmMessage = "Session not opened";
+        break;
+    case ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED:
+        drmMessage = "Not initialized";
+        break;
+    case ERROR_DRM_DECRYPT:
+        drmMessage = "Decrypt error";
+        break;
+    case ERROR_DRM_CANNOT_HANDLE:
+        drmMessage = "Unsupported scheme or data format";
+        break;
+    case ERROR_DRM_TAMPER_DETECTED:
+        drmMessage = "Invalid state";
+        break;
+    default:
+        break;
+    }
+
+    String8 vendorMessage;
+    if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
+        vendorMessage = String8::format("DRM vendor-defined error: %d", err);
+        drmMessage = vendorMessage.string();
+    }
+
+    if (err == BAD_VALUE) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", msg);
+        return true;
+    } else if (err == ERROR_DRM_NOT_PROVISIONED) {
+        jniThrowException(env, "android/media/NotProvisionedException", msg);
+        return true;
+    } else if (err == ERROR_DRM_RESOURCE_BUSY) {
+        jniThrowException(env, "android/media/ResourceBusyException", msg);
+        return true;
+    } else if (err == ERROR_DRM_DEVICE_REVOKED) {
+        jniThrowException(env, "android/media/DeniedByServerException", msg);
+        return true;
+    } else if (err == DEAD_OBJECT) {
+        jniThrowException(env, "android/media/MediaDrmResetException",
+                          "mediaserver died");
+        return true;
+    } else if (err != OK) {
+        String8 errbuf;
+        if (drmMessage != NULL) {
+            if (msg == NULL) {
+                msg = drmMessage;
+            } else {
+                errbuf = String8::format("%s: %s", msg, drmMessage);
+                msg = errbuf.string();
+            }
+        }
+        throwDrmStateException(env, msg, err);
+        return true;
+    }
+    return false;
+}
+
+// TODO: investigate if these can be shared with their MediaDrm counterparts
+static jbyteArray VectorToJByteArray(JNIEnv *env, Vector<uint8_t> const &vector)
+{
+    size_t length = vector.size();
+    jbyteArray result = env->NewByteArray(length);
+    if (result != NULL) {
+        env->SetByteArrayRegion(result, 0, length, (jbyte *)vector.array());
+    }
+    return result;
+}
+
+// TODO: investigate if these can be shared with their MediaDrm counterparts
+static Vector<uint8_t> JByteArrayToVector(JNIEnv *env, jbyteArray const &byteArray)
+{
+    Vector<uint8_t> vector;
+    size_t length = env->GetArrayLength(byteArray);
+    vector.insertAt((size_t)0, length);
+    env->GetByteArrayRegion(byteArray, 0, length, (jbyte *)vector.editArray());
+    return vector;
+}
+
+// TODO: investigate if these can be shared with their MediaDrm counterparts
+static String8 JStringToString8(JNIEnv *env, jstring const &jstr)
+{
+    String8 result;
+
+    const char *s = env->GetStringUTFChars(jstr, NULL);
+    if (s) {
+        result = s;
+        env->ReleaseStringUTFChars(jstr, s);
+    }
+    return result;
+}
+
+// TODO: investigate if these can be shared with their MediaDrm counterparts
+static KeyedVector<String8, String8> HashMapToKeyedVector(JNIEnv *env,
+                                             jobject &hashMap, bool* pIsOK)
+{
+    jclass clazz = gFields.stringClassId;
+    KeyedVector<String8, String8> keyedVector;
+    *pIsOK = true;
+
+    jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
+    if (entrySet) {
+        jobject iterator = env->CallObjectMethod(entrySet, gFields.set.iterator);
+        if (iterator) {
+            jboolean hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
+            while (hasNext) {
+                jobject entry = env->CallObjectMethod(iterator, gFields.iterator.next);
+                if (entry) {
+                    jobject obj = env->CallObjectMethod(entry, gFields.entry.getKey);
+                    if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
+                        jniThrowException(env, "java/lang/IllegalArgumentException",
+                                          "HashMap key is not a String");
+                        env->DeleteLocalRef(entry);
+                        *pIsOK = false;
+                        break;
+                    }
+                    jstring jkey = static_cast<jstring>(obj);
+
+                    obj = env->CallObjectMethod(entry, gFields.entry.getValue);
+                    if (obj == NULL || !env->IsInstanceOf(obj, clazz)) {
+                        jniThrowException(env, "java/lang/IllegalArgumentException",
+                                          "HashMap value is not a String");
+                        env->DeleteLocalRef(entry);
+                        *pIsOK = false;
+                        break;
+                    }
+                    jstring jvalue = static_cast<jstring>(obj);
+
+                    String8 key = JStringToString8(env, jkey);
+                    String8 value = JStringToString8(env, jvalue);
+                    keyedVector.add(key, value);
+
+                    env->DeleteLocalRef(jkey);
+                    env->DeleteLocalRef(jvalue);
+                    hasNext = env->CallBooleanMethod(iterator, gFields.iterator.hasNext);
+                }
+                env->DeleteLocalRef(entry);
+            }
+            env->DeleteLocalRef(iterator);
+        }
+        env->DeleteLocalRef(entrySet);
+    }
+    return keyedVector;
+}
+
+static void android_media_MediaPlayer_prepareDrm(JNIEnv *env, jobject thiz,
+                    jbyteArray uuidObj, jint mode)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+
+    if (uuidObj == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return;
+    }
+
+    Vector<uint8_t> uuid = JByteArrayToVector(env, uuidObj);
+
+    if (uuid.size() != 16) {
+        jniThrowException(
+                          env,
+                          "java/lang/IllegalArgumentException",
+                          "invalid UUID size, expected 16 bytes");
+        return;
+    }
+
+    status_t err = mp->prepareDrm(uuid.array(), mode);
+    if (err != OK) {
+        if (err == INVALID_OPERATION) {
+            jniThrowException(
+                              env,
+                              "java/lang/IllegalStateException",
+                              "The player is not prepared yet.");
+        } else if (err == ERROR_DRM_CANNOT_HANDLE) {
+            jniThrowException(
+                              env,
+                              "android/media/UnsupportedSchemeException",
+                              "Failed to instantiate drm object.");
+        } else {
+            throwDrmExceptionAsNecessary(env, err, "Failed to prepare DRM scheme");
+        }
+    }
+}
+
+static void android_media_MediaPlayer_releaseDrm(JNIEnv *env, jobject thiz)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+
+    status_t err = mp->releaseDrm();
+    if (err != OK) {
+        if (err == INVALID_OPERATION) {
+            jniThrowException(
+                              env,
+                              "java/lang/IllegalStateException",
+                              "The player is not prepared yet.");
+        }
+    }
+}
+
+static jobject android_media_MediaPlayer_getKeyRequest(JNIEnv *env, jobject thiz, jbyteArray jscope,
+                       jstring jmimeType, jint jkeyType, jobject joptParams)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return NULL;
+    }
+
+    Vector<uint8_t> scope;
+    if (jscope != NULL) {
+        scope = JByteArrayToVector(env, jscope);
+    }
+
+    String8 mimeType;
+    if (jmimeType != NULL) {
+        mimeType = JStringToString8(env, jmimeType);
+    }
+
+    DrmPlugin::KeyType keyType;
+    if (jkeyType == gKeyTypes.kKeyTypeStreaming) {
+        keyType = DrmPlugin::kKeyType_Streaming;
+    } else if (jkeyType == gKeyTypes.kKeyTypeOffline) {
+        keyType = DrmPlugin::kKeyType_Offline;
+    } else if (jkeyType == gKeyTypes.kKeyTypeRelease) {
+        keyType = DrmPlugin::kKeyType_Release;
+    } else {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "invalid keyType");
+        return NULL;
+    }
+
+    KeyedVector<String8, String8> optParams;
+    if (joptParams != NULL) {
+        bool isOK;
+        optParams = HashMapToKeyedVector(env, joptParams, &isOK);
+        if (!isOK) {
+            return NULL;
+        }
+    }
+
+    Vector<uint8_t> request;
+    String8 defaultUrl;
+    DrmPlugin::KeyRequestType keyRequestType;
+    status_t err = mp->getKeyRequest(scope, mimeType, keyType, optParams, request, defaultUrl,
+                           keyRequestType);
+
+    if (throwDrmExceptionAsNecessary(env, err, "Failed to get key request")) {
+        return NULL;
+    }
+
+    ALOGV("JNI getKeyRequest err %d  request %d  url %s  keyReqType %d",
+          err, (int)request.size(), defaultUrl.string(), (int)keyRequestType);
+
+    // Fill out return obj
+    jclass clazz;
+    FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
+
+    jobject keyObj = NULL;
+
+    if (clazz) {
+        keyObj = env->AllocObject(clazz);
+        jbyteArray jrequest = VectorToJByteArray(env, request);
+        env->SetObjectField(keyObj, gFields.keyRequest.data, jrequest);
+
+        jstring jdefaultUrl = env->NewStringUTF(defaultUrl.string());
+        env->SetObjectField(keyObj, gFields.keyRequest.defaultUrl, jdefaultUrl);
+
+        switch (keyRequestType) {
+        case DrmPlugin::kKeyRequestType_Initial:
+            env->SetIntField(keyObj, gFields.keyRequest.requestType,
+                         gKeyRequestTypes.kKeyRequestTypeInitial);
+            break;
+        case DrmPlugin::kKeyRequestType_Renewal:
+            env->SetIntField(keyObj, gFields.keyRequest.requestType,
+                         gKeyRequestTypes.kKeyRequestTypeRenewal);
+            break;
+        case DrmPlugin::kKeyRequestType_Release:
+            env->SetIntField(keyObj, gFields.keyRequest.requestType,
+                         gKeyRequestTypes.kKeyRequestTypeRelease);
+            break;
+        default:
+            throwDrmStateException(env, "MediaPlayer/DRM plugin failure: unknown "
+                    "key request type", ERROR_DRM_UNKNOWN);
+            break;
+        }
+    }
+
+    return keyObj;
+}
+
+static jbyteArray android_media_MediaPlayer_provideKeyResponse(JNIEnv *env, jobject thiz,
+                          jbyteArray jreleaseKeySetId, jbyteArray jresponse)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return NULL;
+    }
+
+    if (jresponse == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "key response is null");
+        return NULL;
+    }
+
+    Vector<uint8_t> releaseKeySetId;
+    if (jreleaseKeySetId != NULL) {
+        releaseKeySetId = JByteArrayToVector(env, jreleaseKeySetId);
+    }
+
+    Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
+    Vector<uint8_t> keySetId;
+
+    status_t err = mp->provideKeyResponse(releaseKeySetId, response, keySetId);
+
+    if (throwDrmExceptionAsNecessary(env, err, "Failed to handle key response")) {
+        return NULL;
+    }
+    return VectorToJByteArray(env, keySetId);
+}
+
+static void android_media_MediaPlayer_restoreKeys(JNIEnv *env, jobject thiz, jbyteArray jkeySetId)
+{
+     sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+     if (mp == NULL) {
+         jniThrowException(env, "java/lang/IllegalStateException", NULL);
+         return;
+     }
+
+    if (jkeySetId == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "invalid keyType");
+        return;
+    }
+
+    Vector<uint8_t> keySetId;
+    keySetId = JByteArrayToVector(env, jkeySetId);
+
+    status_t err = mp->restoreKeys(keySetId);
+
+    ALOGV("JNI restoreKeys err %d ", err);
+    throwDrmExceptionAsNecessary(env, err, "Failed to restore keys");
+}
+
+static jstring android_media_MediaPlayer_getDrmPropertyString(JNIEnv *env, jobject thiz,
+                       jstring jname)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return NULL;
+    }
+
+    if (jname == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                "property name String is null");
+        return NULL;
+    }
+
+    String8 name = JStringToString8(env, jname);
+    String8 value;
+
+    status_t err = mp->getDrmPropertyString(name, value);
+
+    ALOGV("JNI getPropertyString err %d", err);
+
+    if (throwDrmExceptionAsNecessary(env, err, "Failed to get property")) {
+        return NULL;
+    }
+
+    return env->NewStringUTF(value.string());
+}
+
+static void android_media_MediaPlayer_setDrmPropertyString(JNIEnv *env, jobject thiz,
+                    jstring jname, jstring jvalue)
+{
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+
+    if (jname == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                "property name String is null");
+        return;
+    }
+
+    if (jvalue == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                "property value String is null");
+        return;
+    }
+
+    String8 name = JStringToString8(env, jname);
+    String8 value = JStringToString8(env, jvalue);
+
+    status_t err = mp->setDrmPropertyString(name, value);
+
+    ALOGV("JNI setPropertyString err %d", err);
+    throwDrmExceptionAsNecessary(env, err, "Failed to set property");
+}
+// Modular DRM end
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod gMethods[] = {
@@ -1046,12 +1707,16 @@
     {"_setDataSource",      "(Ljava/io/FileDescriptor;JJ)V",    (void *)android_media_MediaPlayer_setDataSourceFD},
     {"_setDataSource",      "(Landroid/media/MediaDataSource;)V",(void *)android_media_MediaPlayer_setDataSourceCallback },
     {"_setVideoSurface",    "(Landroid/view/Surface;)V",        (void *)android_media_MediaPlayer_setVideoSurface},
+    {"getDefaultBufferingParams", "()Landroid/media/BufferingParams;", (void *)android_media_MediaPlayer_getDefaultBufferingParams},
+    {"getBufferingParams", "()Landroid/media/BufferingParams;", (void *)android_media_MediaPlayer_getBufferingParams},
+    {"setBufferingParams", "(Landroid/media/BufferingParams;)V", (void *)android_media_MediaPlayer_setBufferingParams},
     {"_prepare",            "()V",                              (void *)android_media_MediaPlayer_prepare},
     {"prepareAsync",        "()V",                              (void *)android_media_MediaPlayer_prepareAsync},
     {"_start",              "()V",                              (void *)android_media_MediaPlayer_start},
     {"_stop",               "()V",                              (void *)android_media_MediaPlayer_stop},
     {"getVideoWidth",       "()I",                              (void *)android_media_MediaPlayer_getVideoWidth},
     {"getVideoHeight",      "()I",                              (void *)android_media_MediaPlayer_getVideoHeight},
+    {"getMetrics",          "()Landroid/os/Bundle;",            (void *)android_media_MediaPlayer_getMetrics},
     {"setPlaybackParams", "(Landroid/media/PlaybackParams;)V", (void *)android_media_MediaPlayer_setPlaybackParams},
     {"getPlaybackParams", "()Landroid/media/PlaybackParams;", (void *)android_media_MediaPlayer_getPlaybackParams},
     {"setSyncParams",     "(Landroid/media/SyncParams;)V",  (void *)android_media_MediaPlayer_setSyncParams},
@@ -1082,6 +1747,15 @@
     {"native_pullBatteryData", "(Landroid/os/Parcel;)I",        (void *)android_media_MediaPlayer_pullBatteryData},
     {"native_setRetransmitEndpoint", "(Ljava/lang/String;I)I",  (void *)android_media_MediaPlayer_setRetransmitEndpoint},
     {"setNextMediaPlayer",  "(Landroid/media/MediaPlayer;)V",   (void *)android_media_MediaPlayer_setNextMediaPlayer},
+    // Modular DRM
+    { "_prepareDrm", "([BI)V",                                  (void *)android_media_MediaPlayer_prepareDrm },
+    { "_releaseDrm", "()V",                                     (void *)android_media_MediaPlayer_releaseDrm },
+    { "_getKeyRequest", "([BLjava/lang/String;ILjava/util/Map;)" "Landroid/media/MediaDrm$KeyRequest;",
+        (void *)android_media_MediaPlayer_getKeyRequest },
+    { "_provideKeyResponse", "([B[B)[B",                        (void *)android_media_MediaPlayer_provideKeyResponse },
+    { "_getDrmPropertyString", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_MediaPlayer_getDrmPropertyString },
+    { "_setDrmPropertyString", "(Ljava/lang/String;Ljava/lang/String;)V",(void *)android_media_MediaPlayer_setDrmPropertyString },
+    { "_restoreKeys", "([B)V",                                  (void *)android_media_MediaPlayer_restoreKeys },
 };
 
 // This function only registers the native methods
diff --git a/media/mca/effect/java/android/media/effect/package.html b/media/mca/effect/java/android/media/effect/package.html
index 8a210fd..1d297ef 100644
--- a/media/mca/effect/java/android/media/effect/package.html
+++ b/media/mca/effect/java/android/media/effect/package.html
@@ -24,7 +24,7 @@
 android.media.effect.EffectContext#getFactory EffectContext.getFactory()}, which returns an instance
 of {@link android.media.effect.EffectFactory}.</li>
 <li>Call {@link android.media.effect.EffectFactory#createEffect createEffect()}, passing it an
-effect name from @link android.media.effect.EffectFactory}, such as {@link
+effect name from {@link android.media.effect.EffectFactory}, such as {@link
 android.media.effect.EffectFactory#EFFECT_FISHEYE} or {@link
 android.media.effect.EffectFactory#EFFECT_VIGNETTE}.</li>
 </ol>
diff --git a/packages/CarrierDefaultApp/res/values-am/strings.xml b/packages/CarrierDefaultApp/res/values-am/strings.xml
new file mode 100644
index 0000000..fc62e8d
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-am/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"አገልግሎትዎን ያግብሩ"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"ምንም የውሂብ አገልግሎት የለም"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"አገልግሎትዎን ለማግበር መታ ያድርጉ"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"ምንም አገልግሎት የለም፣ እባክዎ የአገልግሎት አቅራቢዎን ያነጋግሩ"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"ከተያዥ መግቢያ ጋር በመገናኘት ላይ..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"አውታረ መረብ የእረፍት ጊዜ ወስዷል፣ እንደገና መሞከር ይፈልጋሉ?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"አውታረ መረብ አይገኝም"</string>
+    <string name="quit" msgid="4392968039488794590">"አቁም"</string>
+    <string name="wait" msgid="7902715035629500128">"ይጠብቁ"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-ar/strings.xml b/packages/CarrierDefaultApp/res/values-ar/strings.xml
new file mode 100644
index 0000000..3903c35
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-ar/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"تنشيط الخدمة"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"ليست هناك خدمة بيانات"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"انقر لتنشيط الخدمة"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"ليست هناك خدمة، يرجى الاتصال بمقدم الخدمة"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"جارٍ الاتصال بالمدخل المقيد الوصول..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"انتهت مهلة الشبكة، هل ترغب في إعادة المحاولة؟"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"الشبكة غير متاحة"</string>
+    <string name="quit" msgid="4392968039488794590">"إنهاء"</string>
+    <string name="wait" msgid="7902715035629500128">"انتظار"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml b/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..57f8bf5
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Aktivirajte uslugu"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Nema usluge prenosa podataka"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Dodirnite da biste aktivirali uslugu"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Nema usluge. Kontaktirajte dobavljača usluge"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Povezuje se sa ulaznim portalom…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Vremensko ograničenje mreže je isteklo. Želite li da probate ponovo?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Mreža nije dostupna"</string>
+    <string name="quit" msgid="4392968039488794590">"Zatvori"</string>
+    <string name="wait" msgid="7902715035629500128">"Čekaj"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-be/strings.xml b/packages/CarrierDefaultApp/res/values-be/strings.xml
new file mode 100644
index 0000000..e6d1cd9
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-be/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Актывуйце сэрвіс"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Няма сэрвісу перадачы даных"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Дакраніцеся, каб актываваць сэрвіс"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Няма абслугоўвання, звярніцеся да свайго пастаўшчыка паслуг"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Ідзе падключэнне да партала ўзаемадзеяння..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Час чакання сеткі скончыўся, хочаце паўтарыць спробу?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Сетка недаступная"</string>
+    <string name="quit" msgid="4392968039488794590">"Выйсці"</string>
+    <string name="wait" msgid="7902715035629500128">"Пачакайце"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-bg/strings.xml b/packages/CarrierDefaultApp/res/values-bg/strings.xml
new file mode 100644
index 0000000..b6bdd5d
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-bg/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Активирайте услугата си"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Няма услуга за данни"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Докоснете, за да активирате услугата си"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Няма покритие. Моля, свържете се с доставчика си"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Установява се връзка с портал за удостоверяване..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Времето за изчакване на мрежата изтече. Искате ли да опитате отново?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Мрежата не е налице"</string>
+    <string name="quit" msgid="4392968039488794590">"Изход"</string>
+    <string name="wait" msgid="7902715035629500128">"Изчакване"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-bn/strings.xml b/packages/CarrierDefaultApp/res/values-bn/strings.xml
new file mode 100644
index 0000000..138a2b3
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-bn/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"আপনার পরিষেবা সক্রিয় করুন"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"ডেটা পরিষেবা উপলব্ধ নয়"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"আপনার পরিষেবা সক্রিয় করতে আলতো চাপুন"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"পরিষেবা উপলব্ধ নয়, অনুগ্রহ করে আপনার পরিষেবা প্রদানকারীর সঙ্গে যোগাযোগ করুন"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"অন্তরীণ পোর্টালের সঙ্গে সংযুক্ত করা হচ্ছে..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"নেটওয়ার্কের সময় সমাপ্ত হয়েছে, আপনি কি পুনরায় চেষ্টা করতে চান?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"নেটওয়ার্ক অনুপলব্ধ"</string>
+    <string name="quit" msgid="4392968039488794590">"প্রস্থান করুন"</string>
+    <string name="wait" msgid="7902715035629500128">"অপেক্ষা করুন"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-bs/strings.xml b/packages/CarrierDefaultApp/res/values-bs/strings.xml
new file mode 100644
index 0000000..b43e766
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-bs/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Aktivirajte uslugu"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Nema mobilnog interneta"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Dodirnite da aktivirate uslugu"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Nema usluge. Obratite se pružaocu usluge."</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Povezivanje na zaštitni portal..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Isteklo je vrijeme za odziv mreže. Želite li ponoviti?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Mreža nije dostupna"</string>
+    <string name="quit" msgid="4392968039488794590">"Odustani"</string>
+    <string name="wait" msgid="7902715035629500128">"Sačekaj"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-ca/strings.xml b/packages/CarrierDefaultApp/res/values-ca/strings.xml
new file mode 100644
index 0000000..0730a01
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-ca/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Activa el servei"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"No hi ha servei de dades"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Toca per activar el servei"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"No hi ha servei. Contacta amb el proveïdor del servei."</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"S\'està connectant al portal captiu…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"S\'ha esgotat el temps d\'espera de la xarxa. Vols tornar-ho a provar?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Xarxa no disponible"</string>
+    <string name="quit" msgid="4392968039488794590">"Surt"</string>
+    <string name="wait" msgid="7902715035629500128">"Espera"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-de/strings.xml b/packages/CarrierDefaultApp/res/values-de/strings.xml
new file mode 100644
index 0000000..2713560
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-de/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Dienst aktivieren"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Kein Datendienst"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Zum Aktivieren des Dienstes tippen"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Kein Dienst, kontaktiere bitte deinen Internetanbieter"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Verbindung mit Captive Portal wird hergestellt…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Zeitüberschreitung für Netzwerk – möchtest du es noch einmal versuchen?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Netzwerk nicht verfügbar"</string>
+    <string name="quit" msgid="4392968039488794590">"Beenden"</string>
+    <string name="wait" msgid="7902715035629500128">"Warten"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-el/strings.xml b/packages/CarrierDefaultApp/res/values-el/strings.xml
new file mode 100644
index 0000000..6e9b2a4
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-el/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Ενεργοποιήστε την υπηρεσία σας"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Δεν υπάρχει υπηρεσία δεδομένων"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Πατήστε για να ενεργοποιήσετε την υπηρεσία σας"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Η υπηρεσία δεν είναι διαθέσιμη. Επικοινωνήστε με τον παροχέα υπηρεσιών που χρησιμοποιείτε."</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Σύνδεση στην πύλη υποδοχής…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Λήξη χρονικού ορίου δικτύου, θέλετε να δοκιμάσετε ξανά;"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Το δίκτυο δεν είναι διαθέσιμο"</string>
+    <string name="quit" msgid="4392968039488794590">"Έξοδος"</string>
+    <string name="wait" msgid="7902715035629500128">"Αναμονή"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml b/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..735b255
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Activa tu servicio"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Sin servicio de datos"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Presiona para activar tu servicio"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"No hay servicio, por lo que debes comunicarte con tu proveedor de servicios"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Conectando al portal cautivo…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Se agotó el tiempo de espera de la red, ¿quieres volver a intentarlo?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Red no disponible"</string>
+    <string name="quit" msgid="4392968039488794590">"Salir"</string>
+    <string name="wait" msgid="7902715035629500128">"Esperar"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-es/strings.xml b/packages/CarrierDefaultApp/res/values-es/strings.xml
new file mode 100644
index 0000000..49be628
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-es/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Activar el servicio"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Sin servicio de datos"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Toca aquí para activar tu servicio"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Sin servicio. Ponte en contacto con el proveedor de servicios"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Conectando al portal cautivo…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Se ha agotado el tiempo de espera de la red. ¿Quieres volver a intentarlo?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Red no disponible"</string>
+    <string name="quit" msgid="4392968039488794590">"Salir"</string>
+    <string name="wait" msgid="7902715035629500128">"Esperar"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-et/strings.xml b/packages/CarrierDefaultApp/res/values-et/strings.xml
new file mode 100644
index 0000000..0cdf5bb
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-et/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Aktiveerige teenus"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Andmesideteenus puudub"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Puudutage teenuse aktiveerimiseks"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Teenus puudub. Võtke ühendust oma teenusepakkujaga"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Hõiveportaaliga ühendamine …"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Võrgu ajalõpp. Kas soovite uuesti proovida?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Võrk ei ole saadaval"</string>
+    <string name="quit" msgid="4392968039488794590">"Välju"</string>
+    <string name="wait" msgid="7902715035629500128">"Oodake"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-eu/strings.xml b/packages/CarrierDefaultApp/res/values-eu/strings.xml
new file mode 100644
index 0000000..c1f7fa9
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-eu/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Aktibatu zerbitzua"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Datu-zerbitzua ez dago erabilgarri"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Sakatu zerbitzua aktibatzeko"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Zerbitzua ez dago erabilgarri. Jarri operadorearekin harremanetan."</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Sare-zerbitzuaren atarira konektatzen…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Denbora-muga gainditu du sareak. Berriro saiatu nahi duzu?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Sarea ez dago erabilgarri"</string>
+    <string name="quit" msgid="4392968039488794590">"Irten"</string>
+    <string name="wait" msgid="7902715035629500128">"Itxaron"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-gu/strings.xml b/packages/CarrierDefaultApp/res/values-gu/strings.xml
new file mode 100644
index 0000000..c6d7f96
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-gu/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"કૅરિઅર ડિફૉલ્ટ ઍપ્લિકેશન"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"તમારી સેવા સક્રિય કરો"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"કોઈ ડેટા સેવા ઉપલબ્ધ નથી"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"તમારી સેવા સક્રિય કરવા માટે ટૅપ કરો"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"કોઈ સેવા ઉપલબ્ધ નથી, કૃપા કરીને તમારા સેવા પ્રદાતાનો સંપર્ક કરો"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"કૅપ્ટિવ પોર્ટલ સાથે કનેક્ટ થઈ રહ્યું છે..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"નેટવર્કનો સમય સમાપ્ત થયો, શું તમે ફરીથી પ્રયાસ કરશો?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"નેટવર્ક અનુપલબ્ધ"</string>
+    <string name="quit" msgid="4392968039488794590">"છોડી દો"</string>
+    <string name="wait" msgid="7902715035629500128">"રાહ જુઓ"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-hi/strings.xml b/packages/CarrierDefaultApp/res/values-hi/strings.xml
new file mode 100644
index 0000000..a1de4bc
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-hi/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"अपनी सेवा सक्रिय करें"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"कोई डेटा सेवा नहीं है"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"अपनी सेवा सक्रिय करने के लिए टैप करें"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"कोई सेवा नहीं है, कृपया आपको सेवा प्रदान करने वाले से संपर्क करें"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"कैप्टिव पोर्टल से कनेक्ट हो रहा है..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"नेटवर्क रुक गया है, क्या आप फिर से कोशिश करना चाहेंगे?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"नेटवर्क उपलब्ध नहीं है"</string>
+    <string name="quit" msgid="4392968039488794590">"बाहर निकलें"</string>
+    <string name="wait" msgid="7902715035629500128">"प्रतीक्षा करें"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-hr/strings.xml b/packages/CarrierDefaultApp/res/values-hr/strings.xml
new file mode 100644
index 0000000..d5c05de
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-hr/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"Zadana aplikacija mobilnog operatera"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Aktivirajte uslugu"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Podatkovna usluga nije dostupna"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Dodirnite da biste aktivirali uslugu"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Usluga nije dostupna. Obratite se davatelju usluga."</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Povezivanje sa zaštitnim portalom..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Isteklo je vremensko ograničenje mreže. Želite li pokušati ponovo?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Mreža nije dostupna"</string>
+    <string name="quit" msgid="4392968039488794590">"Izlaz"</string>
+    <string name="wait" msgid="7902715035629500128">"Pričekajte"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-hu/strings.xml b/packages/CarrierDefaultApp/res/values-hu/strings.xml
new file mode 100644
index 0000000..c204ee0
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-hu/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"A szolgáltatás aktiválása"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Az adatszolgáltatás szünetel"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Koppintson a szolgáltatás aktiválásához"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"A szolgáltatás szünetel. Kérjük, vegye fel a kapcsolatot szolgáltatójával."</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Kapcsolódás a hitelesítési portálhoz…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Hálózati időtúllépés. Megpróbálja újra?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"A hálózat nem áll rendelkezésre"</string>
+    <string name="quit" msgid="4392968039488794590">"Kilépés"</string>
+    <string name="wait" msgid="7902715035629500128">"Várakozás"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-hy/strings.xml b/packages/CarrierDefaultApp/res/values-hy/strings.xml
new file mode 100644
index 0000000..ac53574
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-hy/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Ակտիվացրեք ձեր ծառայությունը"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Տվյալների ծառայությունն անհասանելի է"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Հպեք՝ ծառայությունն ակտիվացնելու համար"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Ծառայությունն անհասանելի է։ Դիմեք ձեր ծառայություններ մատուցողին"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Միանում է մուտքի էջին…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Ցանցի սպասման ժամանակը սպառվել է։ Փորձե՞լ կրկին։"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Ցանցն անհասանելի է"</string>
+    <string name="quit" msgid="4392968039488794590">"Դուրս գալ"</string>
+    <string name="wait" msgid="7902715035629500128">"Սպասել"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-in/strings.xml b/packages/CarrierDefaultApp/res/values-in/strings.xml
new file mode 100644
index 0000000..15b6849
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-in/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"AplikasiDefaultOperator"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Aktifkan layanan"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Tidak ada layanan data"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Tap untuk mengaktifkan layanan"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Tidak Ada Layanan, hubungi penyedia layanan"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Menyambungkan ke captive portal..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Waktu tunggu jaringan habis, ingin mencoba lagi?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Jaringan tidak tersedia"</string>
+    <string name="quit" msgid="4392968039488794590">"Keluar"</string>
+    <string name="wait" msgid="7902715035629500128">"Tunggu"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-is/strings.xml b/packages/CarrierDefaultApp/res/values-is/strings.xml
new file mode 100644
index 0000000..fb6ca57
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-is/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Virkja þjónustuna"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Ekkert gagnasamband"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Ýttu til að virkja þjónustuna"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Ekkert samband, hafðu samband við þjónustuaðila"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Tengist innskráningarsíðu..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Tímamörk nettengingar runnu út, viltu reyna aftur?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Ekkert net til staðar"</string>
+    <string name="quit" msgid="4392968039488794590">"Hætta"</string>
+    <string name="wait" msgid="7902715035629500128">"Bíða"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-it/strings.xml b/packages/CarrierDefaultApp/res/values-it/strings.xml
new file mode 100644
index 0000000..fca6eb9
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-it/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Attiva il servizio"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Nessun servizio dati"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Tocca per attivare il servizio"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Nessun servizio. Contatta il provider Internet."</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Connessione al captive portal…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Timeout di rete. Vuoi riprovare?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Rete non disponibile"</string>
+    <string name="quit" msgid="4392968039488794590">"Esci"</string>
+    <string name="wait" msgid="7902715035629500128">"Attendi"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-iw/strings.xml b/packages/CarrierDefaultApp/res/values-iw/strings.xml
new file mode 100644
index 0000000..60b9168
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-iw/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"הפעל את השירות"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"אין שירות נתונים"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"הקש כדי להפעיל את השירות"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"שירות הנתונים לא זמין. צור קשר עם ספק השירות."</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"מתחבר לפורטל שבוי..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"הזמן הקצוב לתפוגת הרשת עבר. תרצה לנסות שוב?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"הרשת אינה זמינה"</string>
+    <string name="quit" msgid="4392968039488794590">"צא"</string>
+    <string name="wait" msgid="7902715035629500128">"המתן"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-ka/strings.xml b/packages/CarrierDefaultApp/res/values-ka/strings.xml
new file mode 100644
index 0000000..c191575
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-ka/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"თქვენი სერვისის გააქტიურება"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"მონაცემთა სერვისი არ არის"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"შეეხეთ თქვენი სერვისის გასააქტიურებლად"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"სერვისი არ არის — გთხოვთ, დაუკავშირდეთ სერვისის პროვაიდერს"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"მიმდინარეობს ავტორიზაციის პორტალთან დაკავშირება…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"ქსელის დროის ლიმიტი ამოიწურა. გსურთ ხელახლა ცდა?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"ქსელი მიუწვდომელია"</string>
+    <string name="quit" msgid="4392968039488794590">"გასვლა"</string>
+    <string name="wait" msgid="7902715035629500128">"მოცდა"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-kk/strings.xml b/packages/CarrierDefaultApp/res/values-kk/strings.xml
new file mode 100644
index 0000000..2285fda
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-kk/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Қызметті іске қосу"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Деректер қызметі көрсетілмейді"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Қызметті іске қосу үшін түртіңіз"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Қызмет көрсетілмейді, қызмет провайдеріне хабарласыңыз"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Адаптивті порталға қосылуда…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Желі мерзімі аяқталды, әрекетті қайталайсыз ба?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Желі қолжетімді емес"</string>
+    <string name="quit" msgid="4392968039488794590">"Шығу"</string>
+    <string name="wait" msgid="7902715035629500128">"Күту"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-kn/strings.xml b/packages/CarrierDefaultApp/res/values-kn/strings.xml
new file mode 100644
index 0000000..42fe9a0
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-kn/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"ನಿಮ್ಮ ಸೇವೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"ಯಾವುದೇ ಡೇಟಾ ಸೇವೆ ಲಭ್ಯವಿಲ್ಲ"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"ನಿಮ್ಮ ಸೇವೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"ಸೇವೆಯು ಲಭ್ಯವಿಲ್ಲ, ನಿಮಗೆ ಸೇವೆ ಒದಗಿಸುವವರನ್ನು ಸಂಪರ್ಕಿಸಿ"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"ವೈ-ಫೈ ಪ್ರಾರಂಭ ಪೋರ್ಟಲ್‌ಗೆ ಸಂಪರ್ಕಿಸಲಾಗುತ್ತಿದೆ..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"ನೆಟ್‌ವರ್ಕ್‌ ಕಾಲಾವಧಿ ಮುಗಿದಿದೆ, ನೀವು ಮತ್ತೊಮ್ಮೆ ಪ್ರಯತ್ನಿಸಲು ಬಯಸುವಿರಾ?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"ನೆಟ್‌ವರ್ಕ್ ಲಭ್ಯವಿಲ್ಲ"</string>
+    <string name="quit" msgid="4392968039488794590">"ತ್ಯಜಿಸಿ"</string>
+    <string name="wait" msgid="7902715035629500128">"ನಿರೀಕ್ಷಿಸಿ"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-ky/strings.xml b/packages/CarrierDefaultApp/res/values-ky/strings.xml
new file mode 100644
index 0000000..54c9575
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-ky/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"ОператордунДемейкиКолдонмосу"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Кызматты жандырыңыз"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Мобилдик туташуу кызматы жок"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Кызматты жандыруу үчүн таптаңыз"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Байланыш жок, кызмат көрсөтүүчүңүзгө кайрылыңыз"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Кирүү бетине туташууда…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Тармактын күтүү убакыты аяктады, кайра аракет кыласызбы?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Тармак жеткиликтүү эмес"</string>
+    <string name="quit" msgid="4392968039488794590">"Чыгуу"</string>
+    <string name="wait" msgid="7902715035629500128">"Күтүү"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-lo/strings.xml b/packages/CarrierDefaultApp/res/values-lo/strings.xml
new file mode 100644
index 0000000..205d9b6
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-lo/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Activate your service"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"No data service"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Tap to activate your service"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"No Service, please contact your service provider"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Connecting to captive portal..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Network timeout, would you like to retry?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Network unavailable"</string>
+    <string name="quit" msgid="4392968039488794590">"ອອກ"</string>
+    <string name="wait" msgid="7902715035629500128">"ລໍ​ຖ້າ"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-lt/strings.xml b/packages/CarrierDefaultApp/res/values-lt/strings.xml
new file mode 100644
index 0000000..61f6d59
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-lt/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Suaktyvinkite paslaugas"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Duomenų paslaugos neteikiamos"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Palieskite, kad suaktyvintumėte paslaugą"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Paslauga neteikiama. Susisiekite su paslaugos teikėju"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Prisijungiama prie fiksuotojo portalo..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Baigėsi skirtasis tinklo laikas. Ar norite bandyti dar kartą?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Tinklas nepasiekiamas"</string>
+    <string name="quit" msgid="4392968039488794590">"Baigti"</string>
+    <string name="wait" msgid="7902715035629500128">"Laukti"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-mk/strings.xml b/packages/CarrierDefaultApp/res/values-mk/strings.xml
new file mode 100644
index 0000000..066fb31
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-mk/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Активирајте ја услугата"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Нема услуга за подотоци"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Допрете за да ја активирате услугата"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Нема услуга, контактирајте со давателот на услуги"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Се поврзува на порталот за автентикација…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Истече времето на мрежата, дали сакате да се обидете повторно?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Мрежата е недостапна"</string>
+    <string name="quit" msgid="4392968039488794590">"Излези"</string>
+    <string name="wait" msgid="7902715035629500128">"Почекај"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-ml/strings.xml b/packages/CarrierDefaultApp/res/values-ml/strings.xml
new file mode 100644
index 0000000..b72e877
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-ml/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"നിങ്ങളുടെ സേവനം ‌ആക്റ്റി‌വേറ്റ് ‌ചെയ്യുക"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"ഡാറ്റ ‌സേവനം ലഭ്യമല്ല"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"നിങ്ങളുടെ സേവനം ‌ആക്റ്റി‌വേറ്റ് ‌ചെയ്യാൻ ടാപ്പുചെയ്യുക"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"സേവനം ‌ലഭ്യമല്ല, നിങ്ങളുടെ ‌സേവന‌ദാതാവിനെ ‌ബന്ധപ്പെടുക"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"ക്യാപ്റ്റീവ് പോർട്ടലിലേയ്ക്ക് കണക്റ്റുചെയ്യുന്നു..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"നെറ്റ്‌വർക്ക് കാലഹരണപ്പെട്ടു, വീണ്ടും ശ്രമിക്കണോ?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"നെറ്റ്‌വർക്ക് ലഭ്യമല്ല"</string>
+    <string name="quit" msgid="4392968039488794590">"പുറത്തുപോവുക"</string>
+    <string name="wait" msgid="7902715035629500128">"കാത്തിരിക്കുക"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-mn/strings.xml b/packages/CarrierDefaultApp/res/values-mn/strings.xml
new file mode 100644
index 0000000..c262e8f
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-mn/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Үйлчилгээгээ идэвхжүүлнэ үү"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Дата үйлчилгээ алга"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Үйлчилгээгээ идэвхжүүлэхийн тулд товшино уу"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Үйлчилгээ алга. Үйлчилгээ үзүүлэгчтэйгээ холбогдоно уу"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Дамжих порталд холбогдож байна..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Сүлжээний хугацаа дууссан байна. Дахин оролдох уу?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Сүлжээ боломжгүй"</string>
+    <string name="quit" msgid="4392968039488794590">"Гарах"</string>
+    <string name="wait" msgid="7902715035629500128">"Хүлээх"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-mr/strings.xml b/packages/CarrierDefaultApp/res/values-mr/strings.xml
new file mode 100644
index 0000000..beff675
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-mr/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"आपली सेवा सक्रिय करा"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"डेटा सेवा नाही"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"आपली सेवा सक्रिय करण्यासाठी टॅप करा"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"सेवा नाही, कृपया आपल्या सेवा प्रदात्याशी संपर्क साधा"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"कॅप्टिव्ह पोर्टलशी कनेक्ट करत आहे..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"नेटवर्क कालबाह्य झाले, आपण पुन्हा प्रयत्न करू इच्छिता का?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"नेटवर्क अनुपलब्ध"</string>
+    <string name="quit" msgid="4392968039488794590">"बाहेर पडा"</string>
+    <string name="wait" msgid="7902715035629500128">"प्रतीक्षा करा"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-my/strings.xml b/packages/CarrierDefaultApp/res/values-my/strings.xml
new file mode 100644
index 0000000..b0e929e
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-my/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"ဝန်ဆောင်မှုကို စဖွင့်အသုံးပြုရန်"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"ဒေတာချိတ်ဆက်မှုမရှိပါ"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"ဝန်ဆောင်မှုကို စဖွင့်အသုံးပြုရန် တို့ပါ"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"လိုင်းမရှိပါ။ သင့်ဝန်ဆောင်မှုပေးသူကို ဆက်သွယ်ပါ"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"captive portal သို့ ချိတ်ဆက်နေသည်..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"ချိတ်ဆက်မှု ပြတ်တောက်သွားပါသည်။ ထပ်လုပ်လိုပါသလား။"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"ကွန်ရက်ချိတ်ဆက်မှု မရှိပါ"</string>
+    <string name="quit" msgid="4392968039488794590">"ထွက်ရန်"</string>
+    <string name="wait" msgid="7902715035629500128">"စောင့်ရန်"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-nb/strings.xml b/packages/CarrierDefaultApp/res/values-nb/strings.xml
new file mode 100644
index 0000000..6f69e9a
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-nb/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Aktiver tjenesten"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Ingen datatjeneste"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Trykk for å aktivere tjenesten"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Ingen dekning – ta kontakt med tjenesteleverandøren din."</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Kobler til obligatorisk side …"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Tidsavbrudd for nettverk – vil du prøve på nytt?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Nettverket er utilgjengelig"</string>
+    <string name="quit" msgid="4392968039488794590">"Avslutt"</string>
+    <string name="wait" msgid="7902715035629500128">"Vent"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-ne/strings.xml b/packages/CarrierDefaultApp/res/values-ne/strings.xml
new file mode 100644
index 0000000..aa5766b
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-ne/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"आफ्नो सेवालाई सक्रिय पार्नुहोस्‌"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"डेटा सेवा छैन"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"आफ्नो सेवालाई सक्रिय पार्न ट्याप गर्नुहोस्"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"सेवा उपलब्ध छैन,कृपया आफ्नो सेवा प्रदायकलाई सम्पर्क गर्नुहोस्"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"क्याप्टिभ पोर्टलमा जडान हुँदैछ..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"नेटवर्कमा जडान हुने समय समाप्त भयो, के तपाईँ पुनः प्रयास गर्न चाहानुहुन्छ?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"नेटवर्क उपलब्ध छैन"</string>
+    <string name="quit" msgid="4392968039488794590">"बाहिरिनुहोस्"</string>
+    <string name="wait" msgid="7902715035629500128">"पर्खनुहोस्"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-nl/strings.xml b/packages/CarrierDefaultApp/res/values-nl/strings.xml
new file mode 100644
index 0000000..b7da335
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-nl/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"De service activeren"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Geen gegevensservice"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Tik om de service te activeren"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Geen service. Neem contact op met je serviceprovider."</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Verbinding maken met captive portal..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Time-out voor het netwerk. Wil je het opnieuw proberen?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Netwerk niet beschikbaar"</string>
+    <string name="quit" msgid="4392968039488794590">"Stoppen"</string>
+    <string name="wait" msgid="7902715035629500128">"Wachten"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-pa/strings.xml b/packages/CarrierDefaultApp/res/values-pa/strings.xml
new file mode 100644
index 0000000..ea07e88
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-pa/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"ਆਪਣੀ ਸੇਵਾ ਨੂੰ ਸਰਗਰਮ ਕਰੋ"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"ਕੋਈ ਡੈਟਾ ਸੇਵਾ ਨਹੀਂ"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"ਆਪਣੀ ਸੇਵਾ ਨੂੰ ਸਰਗਰਮ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"ਕੋਈ ਸੇਵਾ ਨਹੀਂ, ਕਿਰਪਾ ਕਰਕੇ ਆਪਣੇ ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"ਕੈਪਟਿਵ ਪੋਰਟਲ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"ਨੈੱਟਵਰਕ ਦਾ ਸਮਾਂ ਸਮਾਪਤ ਹੋ ਗਿਆ, ਕੀ ਤੁਸੀਂ ਮੁੜ-ਕੋਸ਼ਿਸ਼ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"ਨੈੱਟਵਰਕ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
+    <string name="quit" msgid="4392968039488794590">"ਛੱਡੋ"</string>
+    <string name="wait" msgid="7902715035629500128">"ਉਡੀਕ ਕਰੋ"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml b/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000..e730dc6
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Ative seu serviço"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Sem serviço de dados"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Toque para ativar seu serviço"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Sem serviço. Entre em contato com seu provedor de serviços"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Conectando-se ao portal cativo…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Tempo limite de rede. Deseja tentar novamente?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Rede indisponível"</string>
+    <string name="quit" msgid="4392968039488794590">"Sair"</string>
+    <string name="wait" msgid="7902715035629500128">"Esperar"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml b/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..a2c10e9
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Ativar o seu serviço"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Sem serviço de dados"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Toque para ativar o seu serviço"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Sem serviço. Contacte o seu fornecedor de serviços"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"A ligar ao portal cativo…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"O limite de tempo da rede foi excedido. Pretende tentar novamente?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Rede não disponível"</string>
+    <string name="quit" msgid="4392968039488794590">"Sair"</string>
+    <string name="wait" msgid="7902715035629500128">"Aguardar"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-pt/strings.xml b/packages/CarrierDefaultApp/res/values-pt/strings.xml
new file mode 100644
index 0000000..e730dc6
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-pt/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Ative seu serviço"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Sem serviço de dados"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Toque para ativar seu serviço"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Sem serviço. Entre em contato com seu provedor de serviços"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Conectando-se ao portal cativo…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Tempo limite de rede. Deseja tentar novamente?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Rede indisponível"</string>
+    <string name="quit" msgid="4392968039488794590">"Sair"</string>
+    <string name="wait" msgid="7902715035629500128">"Esperar"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-ro/strings.xml b/packages/CarrierDefaultApp/res/values-ro/strings.xml
new file mode 100644
index 0000000..234c410
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-ro/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"AplicațiePrestabilităOperator"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Activați serviciul"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Fără serviciu de date"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Atingeți pentru a activa serviciul"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Fără serviciu. Contactați furnizorul de servicii."</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Se conectează la portalul captiv..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Timpul limită pentru rețea a expirat. Doriți să încercați din nou?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Rețea indisponibilă"</string>
+    <string name="quit" msgid="4392968039488794590">"Ieșiți"</string>
+    <string name="wait" msgid="7902715035629500128">"Așteptați"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-ru/strings.xml b/packages/CarrierDefaultApp/res/values-ru/strings.xml
new file mode 100644
index 0000000..b038f0f
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-ru/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Активируйте сервис"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Нет подключения"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Нажмите, чтобы активировать сервис"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Обратитесь к своему поставщику услуг Интернета."</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Подключение к странице входа…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Время ожидания для сети истекло. Повторить попытку?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Сеть недоступна"</string>
+    <string name="quit" msgid="4392968039488794590">"Закрыть"</string>
+    <string name="wait" msgid="7902715035629500128">"Подождать"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-sk/strings.xml b/packages/CarrierDefaultApp/res/values-sk/strings.xml
new file mode 100644
index 0000000..a73e55c
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-sk/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"Predvolená aplikácia operátora"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Aktivujte službu"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Žiadna dátová služba"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Klepnutím aktivujete službu"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Žiadna služba, kontaktujte svojho poskytovateľa služieb"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Pripájanie k prihlasovaciemu portálu…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Vypršal časový limit siete. Chcete to skúsiť znova?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Sieť nie je k dispozícii"</string>
+    <string name="quit" msgid="4392968039488794590">"Ukončiť"</string>
+    <string name="wait" msgid="7902715035629500128">"Počkať"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-sq/strings.xml b/packages/CarrierDefaultApp/res/values-sq/strings.xml
new file mode 100644
index 0000000..316fe1d
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-sq/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Aktivizo shërbimin"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Nuk ka shërbim për të dhënat"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Trokit për të aktivizuar shërbimin"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Nuk ka shërbim, kontakto me ofruesin e shërbimit"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Po lidhet me portalin e izoluar..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Koha e pritjes së rrjetit përfundoi. Dëshiron të provosh sërish?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Rrjeti është i padisponueshëm"</string>
+    <string name="quit" msgid="4392968039488794590">"Dil"</string>
+    <string name="wait" msgid="7902715035629500128">"Prit"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-sr/strings.xml b/packages/CarrierDefaultApp/res/values-sr/strings.xml
new file mode 100644
index 0000000..5c381f4
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-sr/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Активирајте услугу"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Нема услуге преноса података"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Додирните да бисте активирали услугу"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Нема услуге. Контактирајте добављача услуге"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Повезује се са улазним порталом…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Временско ограничење мреже је истекло. Желите ли да пробате поново?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Мрежа није доступна"</string>
+    <string name="quit" msgid="4392968039488794590">"Затвори"</string>
+    <string name="wait" msgid="7902715035629500128">"Чекај"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-sw/strings.xml b/packages/CarrierDefaultApp/res/values-sw/strings.xml
new file mode 100644
index 0000000..dfcc5c4
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-sw/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Anzisha huduma yako"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Hakuna huduma ya data"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Gonga ili uanzishe huduma yako"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Hakuna Huduma, tafadhali wasiliana na mtoa huduma wako"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Inaunganisha kwenye ukurasa wa mwanzo..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Muda wa kutumia mtandao umekwisha, ungependa kujaribu tena?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Mtandao haupatikani"</string>
+    <string name="quit" msgid="4392968039488794590">"Ondoka"</string>
+    <string name="wait" msgid="7902715035629500128">"Subiri"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-te/strings.xml b/packages/CarrierDefaultApp/res/values-te/strings.xml
new file mode 100644
index 0000000..70fe499
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-te/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"మీ సేవని సక్రియం చేయండి"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"డేటా సేవ లేదు"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"మీ సేవని సక్రియం చేయడానికి నొక్కండి"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"సేవ లేదు, దయచేసి మీ సేవా ప్రదాతను సంప్రదించండి"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"క్యాప్టివ్ పోర్టల్‌కు కనెక్ట్ చేస్తోంది..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"నెట్‌వర్క్ గడువు సమయం ముగిసింది, మీరు మళ్లీ ప్రయత్నించాలనుకుంటున్నారా?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"నెట్‌వర్క్ అందుబాటులో లేదు"</string>
+    <string name="quit" msgid="4392968039488794590">"నిష్క్రమించు"</string>
+    <string name="wait" msgid="7902715035629500128">"వేచి ఉండండి"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-th/strings.xml b/packages/CarrierDefaultApp/res/values-th/strings.xml
new file mode 100644
index 0000000..66526ea
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-th/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"เปิดใช้งานบริการของคุณ"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"ไม่มีบริการข้อมูล"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"แตะเพื่อเปิดใช้งานบริการ"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"ไม่มีบริการ โปรดติดต่อผู้ให้บริการ"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"กำลังเชื่อมต่อแคพทีฟพอร์ทัล..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"หมดเวลาเชื่อมต่อเครือข่ายแล้ว ลองอีกครั้งไหม"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"เครือข่ายใช้ไม่ได้"</string>
+    <string name="quit" msgid="4392968039488794590">"ปิด"</string>
+    <string name="wait" msgid="7902715035629500128">"รอ"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-ur/strings.xml b/packages/CarrierDefaultApp/res/values-ur/strings.xml
new file mode 100644
index 0000000..3002d40
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-ur/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"اپنی سروس فعال کریں"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"ڈیٹا سروس موجود نہیں"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"اپنی سروس فعال کرنے کے لیے تھپتھپائیں"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"سروس موجود نہیں، براہ کرم اپنے خدمت کے فراہم کنندہ سے رابطہ کریں"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"کیپٹو پورٹل سے منسلک ہو رہا ہے..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"نیٹ ورک ٹائم آؤٹ، کیا آپ دوبارہ کوشش کرنا چاہیں گے؟"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"نیٹ ورک غیر دستیاب ہے"</string>
+    <string name="quit" msgid="4392968039488794590">"چھوڑ دیں"</string>
+    <string name="wait" msgid="7902715035629500128">"انتظار کریں"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-uz/strings.xml b/packages/CarrierDefaultApp/res/values-uz/strings.xml
new file mode 100644
index 0000000..92a0af0
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-uz/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Xizmatni faollashtiring"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Aloqa yo‘q"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Xizmatni faollashtirish uchun bosing"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Xizmat yo‘q. Xizmat ta’minotchisi bilan bog‘laning."</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Kirish sahifasida haqiqiylik tekshiruvi bor tarmoqqa ulanilmoqda…"</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Tarmoq uchun kutish vaqti tugadi. Qayta urinilsinmi?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Tarmoq mavjud emas"</string>
+    <string name="quit" msgid="4392968039488794590">"Chiqish"</string>
+    <string name="wait" msgid="7902715035629500128">"Kutish"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-vi/strings.xml b/packages/CarrierDefaultApp/res/values-vi/strings.xml
new file mode 100644
index 0000000..06ea6f0
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-vi/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Kích hoạt dịch vụ của bạn"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Không có dịch vụ dữ liệu"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Nhấn để kích hoạt dịch vụ của bạn"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Không có dịch vụ, vui lòng liên hệ với nhà cung cấp dịch vụ của bạn"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Đang kết nối với cổng cố định..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Hết thời gian chờ mạng, bạn có muốn thử lại không?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Mạng không khả dụng"</string>
+    <string name="quit" msgid="4392968039488794590">"Thoát"</string>
+    <string name="wait" msgid="7902715035629500128">"Đợi"</string>
+</resources>
diff --git a/packages/CarrierDefaultApp/res/values-zu/strings.xml b/packages/CarrierDefaultApp/res/values-zu/strings.xml
new file mode 100644
index 0000000..12e8a7d
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/values-zu/strings.xml
@@ -0,0 +1,14 @@
+<?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_name" msgid="5247871339820894594">"CarrierDefaultApp"</string>
+    <string name="portal_notification_id" msgid="267536768510843288">"Sebenzisa isevisi yakho"</string>
+    <string name="no_data_notification_id" msgid="5216950045164991172">"Ayikho isevisi yedatha"</string>
+    <string name="portal_notification_detail" msgid="2860620550281695686">"Thepha ukuze usebenzise isevisi yakho"</string>
+    <string name="no_data_notification_detail" msgid="1757413358517680719">"Ayikho isevisi, sicela uxhumane nomhlinzeki wakho wesevisi"</string>
+    <string name="progress_dialogue_network_connection" msgid="4964125154591905581">"Ixhuma kuphothali yabathunjiweyo..."</string>
+    <string name="alert_dialogue_network_timeout" msgid="4515760047815901797">"Ukuphela kwesikhathi senethiwekhi, ungathanda ukuzama futhi?"</string>
+    <string name="alert_dialogue_network_timeout_title" msgid="3117252205484891837">"Inethiwekhi ayitholakali"</string>
+    <string name="quit" msgid="4392968039488794590">"Yeka"</string>
+    <string name="wait" msgid="7902715035629500128">"Linda"</string>
+</resources>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 63fa08c..a097b18 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Hulp en terugvoer"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Kieslys"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"MGT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Voer wagwoord in om fabriekterugstelling in demonstrasiemodus uit te voer"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Volgende"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Wagwoord word benodig"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-am/arrays.xml b/packages/SettingsLib/res/values-am/arrays.xml
index 5f35d32..8746cc8 100644
--- a/packages/SettingsLib/res/values-am/arrays.xml
+++ b/packages/SettingsLib/res/values-am/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"ለDRM ይዘት ብቻ HDCP  ምልከታን ተጠቀም"</item>
     <item msgid="45075631231212732">"ሁልጊዜ የHDCP ምልከታ ተጠቀም"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item>
+    <item msgid="8895532488906185219">"44.1 ኪኸ"</item>
+    <item msgid="2909915718994807056">"48.0 ኪኸ"</item>
+    <item msgid="3347287377354164611">"88.2 ኪኸ"</item>
+    <item msgid="1234212100239985373">"96.0 ኪኸ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item>
+    <item msgid="4482862757811638365">"44.1 ኪኸ"</item>
+    <item msgid="354495328188724404">"48.0 ኪኸ"</item>
+    <item msgid="7329816882213695083">"88.2 ኪኸ"</item>
+    <item msgid="6967397666254430476">"96.0 ኪኸ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item>
+    <item msgid="5618929009984956469">"16 ቢት/ናሙና"</item>
+    <item msgid="3412640499234627248">"24 ቢት/ናሙና"</item>
+    <item msgid="121583001492929387">"32 ቢት/ናሙና"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item>
+    <item msgid="4726688794884191540">"16 ቢት/ናሙና"</item>
+    <item msgid="305344756485516870">"24 ቢት/ናሙና"</item>
+    <item msgid="244568657919675099">"32 ቢት/ናሙና"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item>
+    <item msgid="4106832974775067314">"ሞኖ"</item>
+    <item msgid="5571632958424639155">"ስቲሪዮ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"የስርዓቱን ምርጫ (ነባሪ) ተጠቀም"</item>
+    <item msgid="8900559293912978337">"ሞኖ"</item>
+    <item msgid="8883739882299884241">"ስቲሪዮ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"ለኦዲዮ ጥራት አትባ (990 ኪቢ/ሴ / 909 ኪቢ/ሴ)"</item>
+    <item msgid="2921767058740704969">"ለኦዲዮ ጥራት አትባ (660 ኪቢ/ሴ / 606 ኪቢ/ሴ)"</item>
+    <item msgid="3682554248829489641">"ለኦዲዮ ጥራት አትባ (330 ኪቢ/ሴ / 303 ኪቢ/ሴ)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"የኦዲዮ ጥራት አትባ"</item>
+    <item msgid="4327143584633311908">"የተመጣጠነ የኦዲዮ እና ግንኙነት ጥራት"</item>
+    <item msgid="6155648878105378550">"ለግንኙነት ጥራት አትባ"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"ጠፍቷል"</item>
     <item msgid="1593289376502312923">"64 ኪባ"</item>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 8ecef6e..7725827 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"የተንቀስቃሽ ስልክ ውሂብ ሁልጊዜ ንቁ"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ፍጹማዊ ድምፅን አሰናክል"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"የብሉቱዝ ኦዲዮ ኮዴክ"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"የብሉቱዝ ኦዲዮ ኮዴክ ይምረጡ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"የብሉቱዝ ኦዲዮ ናሙና ፍጥነት"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"የብሉቱዝ ኦዲዮ ኮዴክ ይምረጡ፦\nየናሙና ፍጥነት"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"የብሉቱዝ ኦዲዮ ቢት በናሙና"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"የብሉቱዝ ኦዲዮ ኮዴክ ይምረጡ፦\nቢት በናሙና"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"የብሉቱዝ ኦዲዮ ሰርጥ ሁነታ"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"የብሉቱዝ ኦዲዮ ኮዴክ ይምረጡ፦\nየሰርጥ ሁነታ"</string>
+    <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_verbose_logging_summary" msgid="6615071616111731958">"የWi‑Fi ምዝግብ ማስታወሻ አያያዝ ደረጃ ጨምር፣ በWi‑Fi መምረጫ ውስጥ በአንድ SSID RSSI አሳይ"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"ሲነቃ የWi‑Fi ምልክት ዝቅተኛ ሲሆን Wi‑Fi የውሂብ ግንኙነት ለተንቀሳቃሽ ማስረከብ ላይ ይበልጥ አስገዳጅ ይሆናል"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"እገዛ እና ግብረመልስ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"ምናሌ"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"ጂኤምቲ"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"የፋብሪካ ዳግም ማስጀመር በማሳያ ሁነታ ውስጥ ለማከናወን የይለፍ ቃል ያስገቡ"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"ቀጣይ"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"የይለፍ ቃል ያስፈልጋል"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml
index f7f771a..e7b778c 100644
--- a/packages/SettingsLib/res/values-ar/arrays.xml
+++ b/packages/SettingsLib/res/values-ar/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"‏استخدام التحقق من HDCP لمحتوى DRM فقط"</item>
     <item msgid="45075631231212732">"‏استخدام التحقق من HDCP دومًا"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"استخدام اختيار النظام (افتراضي)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"استخدام اختيار النظام (افتراضي)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"استخدام اختيار النظام (افتراضي)"</item>
+    <item msgid="8895532488906185219">"44.1 كيلو هرتز"</item>
+    <item msgid="2909915718994807056">"48.0 كيلو هرتز"</item>
+    <item msgid="3347287377354164611">"88.2 كيلو هرتز"</item>
+    <item msgid="1234212100239985373">"96.0 كيلو هرتز"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"استخدام اختيار النظام (افتراضي)"</item>
+    <item msgid="4482862757811638365">"44.1 كيلو هرتز"</item>
+    <item msgid="354495328188724404">"48.0 كيلو هرتز"</item>
+    <item msgid="7329816882213695083">"88.2 كيلو هرتز"</item>
+    <item msgid="6967397666254430476">"96.0 كيلو هرتز"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"استخدام اختيار النظام (افتراضي)"</item>
+    <item msgid="5618929009984956469">"16 بت لكل عيّنة"</item>
+    <item msgid="3412640499234627248">"24 بت لكل عيّنة"</item>
+    <item msgid="121583001492929387">"32 بت لكل عيّنة"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"استخدام اختيار النظام (افتراضي)"</item>
+    <item msgid="4726688794884191540">"16 بت لكل عيّنة"</item>
+    <item msgid="305344756485516870">"24 بت لكل عيّنة"</item>
+    <item msgid="244568657919675099">"32 بت لكل عيّنة"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"استخدام اختيار النظام (افتراضي)"</item>
+    <item msgid="4106832974775067314">"أحادي"</item>
+    <item msgid="5571632958424639155">"استريو"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"استخدام اختيار النظام (افتراضي)"</item>
+    <item msgid="8900559293912978337">"أحادي"</item>
+    <item msgid="8883739882299884241">"استريو"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"تحسين جودة الصوت (990 كيلوبت في الثانية/909 كيلوبت في الثانية)"</item>
+    <item msgid="2921767058740704969">"جودة متوازنة للصوت والاتصال (660 كيلوبت في الثانية/606 كيلوبت في الثانية)"</item>
+    <item msgid="3682554248829489641">"تحسين جودة الاتصال (330 كيلوبت في الثانية/303 كيلوبت في الثانية)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"تحسين جودة الصوت"</item>
+    <item msgid="4327143584633311908">"جودة متوازنة للصوت والاتصال"</item>
+    <item msgid="6155648878105378550">"تحسين جودة الاتصال"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"إيقاف"</item>
     <item msgid="1593289376502312923">"٦٤ كيلوبايت"</item>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 4a1e916..fa7e253 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"بيانات الجوّال نشطة دائمًا"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"تعطيل مستوى الصوت المطلق"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ترميز صوت بلوتوث"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"اختيار برنامج الترميز لصوت البلوتوث"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"معدّل عيّنة صوت بلوتوث"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"اختيار برنامج ترميز صوت البلوتوث:\nمعدل العينة"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"وحدات البت لكل عيّنة في صوت بلوتوث"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"اختيار برنامج ترميز صوت البلوتوث:\nوحدات بت لكل عينة"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"وضع قناة صوت بلوتوث"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"اختيار برنامج ترميز صوت البلوتوث:\nوضع القناة"</string>
+    <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_verbose_logging_summary" msgid="6615071616111731958">"‏زيادة مستوى تسجيل Wi-Fi، وعرض لكل SSID RSSI في منتقي Wi-Fi"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"‏عند تمكينه، سيكون Wi-Fi أكثر حدة في تسليم اتصال البيانات إلى الشبكة الخلوية، وذلك عندما تكون إشارة WiFi منخفضة"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"المساعدة والتعليقات"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"القائمة"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"غرينيتش"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"إدخال كلمة المرور لإعادة الضبط بحسب بيانات المصنع في الوضع التجريبي"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"التالي"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"يلزم توفر كلمة مرور"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index ac854c6..db58c5c 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Yardım və rəy"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menyu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Demo rejimində sıfırlamaq üçün parol daxil edin"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Növbəti"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Parol tələb olunur"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
index bde7f58..ab3b8b9 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Koristi izbor sistema (podrazumevano)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Koristi izbor sistema (podrazumevano)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Koristi izbor sistema (podrazumevano)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48,0 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Koristi izbor sistema (podrazumevano)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48,0 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Koristi izbor sistema (podrazumevano)"</item>
+    <item msgid="5618929009984956469">"16 bitova po uzorku"</item>
+    <item msgid="3412640499234627248">"24 bita po uzorku"</item>
+    <item msgid="121583001492929387">"32 bita po uzorku"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Koristi izbor sistema (podrazumevano)"</item>
+    <item msgid="4726688794884191540">"16 bitova po uzorku"</item>
+    <item msgid="305344756485516870">"24 bita po uzorku"</item>
+    <item msgid="244568657919675099">"32 bita po uzorku"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Koristi izbor sistema (podrazumevano)"</item>
+    <item msgid="4106832974775067314">"Mono"</item>
+    <item msgid="5571632958424639155">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Koristi izbor sistema (podrazumevano)"</item>
+    <item msgid="8900559293912978337">"Mono"</item>
+    <item msgid="8883739882299884241">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Optimizuj za kvalitet zvuka (990 kb/s/909 kb/s)"</item>
+    <item msgid="2921767058740704969">"Ujednačen kvalitet zvuka i veze (660 kb/s/606 kb/s)"</item>
+    <item msgid="3682554248829489641">"Optimizuj za kvalitet veze (330 kb/s/303 kb/s)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Optimizuje se za kvalitet zvuka"</item>
+    <item msgid="4327143584633311908">"Ujednačen kvalitet zvuka i veze"</item>
+    <item msgid="6155648878105378550">"Optimizuje se za kvalitet veze"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Isključeno"</item>
     <item msgid="1593289376502312923">"64 kB"</item>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 62be8b2..0aa9524 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Podaci za mobilne uređaje su uvek aktivni"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogući glavno podešavanje jačine zvuka"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth audio kodek"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Izaberite Bluetooth audio kodek"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Brzina uzorkovanja za Bluetooth audio"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Izaberite Bluetooth audio kodek:\nbrzina uzorkovanja"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bitova po uzorku za Bluetooth audio"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Izaberite Bluetooth audio kodek:\nbitova po uzorku"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Režim kanala za Bluetooth audio"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Izaberite Bluetooth audio kodek:\nrežim kanala"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth audio kodek LDAC: kvalitet reprodukcije"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Izaberite Bluetooth audio kodek LDAC:\nkvalitet reprodukcije"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Strimovanje: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Prikaz opcija za sertifikaciju bežičnog ekrana"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećava nivo evidentiranja za Wi‑Fi. Prikaz po SSID RSSI-u u biraču Wi‑Fi mreže"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Kada se omogući, Wi‑Fi će biti agresivniji pri prebacivanju mreže za prenos podataka na Mobilnu, kada je Wi‑Fi signal slab"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Pomoć i povratne informacije"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meni"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Unesite lozinku da biste obavili resetovanje na fabrička podešavanja u režimu demonstracije"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Dalje"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Potrebna je lozinka"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-be/arrays.xml b/packages/SettingsLib/res/values-be/arrays.xml
index 50842cf..f5b2bb3 100644
--- a/packages/SettingsLib/res/values-be/arrays.xml
+++ b/packages/SettingsLib/res/values-be/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"Выкарыстанне праверкі HDCP только для змесціва, абароненага DRM"</item>
     <item msgid="45075631231212732">"Заўсёды выкарыстоўваць праверку HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Выкарыстоўв. выбар сістэмы (стандартны)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Выкарыстоўв. выбар сістэмы (стандартны)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Выкарыстоўв. выбар сістэмы (стандартны)"</item>
+    <item msgid="8895532488906185219">"44,1 кГц"</item>
+    <item msgid="2909915718994807056">"48,0 кГц"</item>
+    <item msgid="3347287377354164611">"88,2 кГц"</item>
+    <item msgid="1234212100239985373">"96,0 кГц"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Выкарыстоўв. выбар сістэмы (стандартны)"</item>
+    <item msgid="4482862757811638365">"44,1 кГц"</item>
+    <item msgid="354495328188724404">"48,0 кГц"</item>
+    <item msgid="7329816882213695083">"88,2 кГц"</item>
+    <item msgid="6967397666254430476">"96,0 кГц"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Выкарыстоўв. выбар сістэмы (стандартны)"</item>
+    <item msgid="5618929009984956469">"16 бітаў/сэмпл"</item>
+    <item msgid="3412640499234627248">"24 біты/сэмпл"</item>
+    <item msgid="121583001492929387">"32 біты/сэмпл"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Выкарыстоўв. выбар сістэмы (стандартны)"</item>
+    <item msgid="4726688794884191540">"16 бітаў/сэмпл"</item>
+    <item msgid="305344756485516870">"24 біты/сэмпл"</item>
+    <item msgid="244568657919675099">"32 біты/сэмпл"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Выкарыстоўв. выбар сістэмы (стандартны)"</item>
+    <item msgid="4106832974775067314">"Мона"</item>
+    <item msgid="5571632958424639155">"Стэрэа"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Выкарыстоўв. выбар сістэмы (стандартны)"</item>
+    <item msgid="8900559293912978337">"Мона"</item>
+    <item msgid="8883739882299884241">"Стэрэа"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Аптымізацыя якасці гуку (990 кбіт/c / 909 кбіт/c)"</item>
+    <item msgid="2921767058740704969">"Збалансаваная якасць аўдыя і падключэння (660кбіт/c / 606 кбіт/c)"</item>
+    <item msgid="3682554248829489641">"Аптымізацыя якасці падключэння (330 кбіт/c / 303 кбіт/c)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Аптымізацыя якасці гуку"</item>
+    <item msgid="4327143584633311908">"Збалансаваная якасць аўдыя і падключэння"</item>
+    <item msgid="6155648878105378550">"Аптымізацыя якасці падключэння"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Выкл."</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index f50253b..6fd82eb 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Перадача даных мабільнай сувязі заўсёды актыўна"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Адключыць абсалютны гук"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Кодэк Bluetooth Audio"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Выбраць аўдыякодэк Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Частата дыскрэтызацыі Bluetooth Audio"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Выбраць аўдыякодэк Bluetooth:\nчастата дыскрэтызацыі"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Біты на сэмпл для Bluetooth Audio"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Выбраць аўдыякодэк Bluetooth:\nбіты на сэмпл"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Канальны рэжым Bluetooth Audio"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Выбраць аўдыякодэк Bluetooth:\nканальны рэжым"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Аўдыякодэк Bluetooth Audio LDAC: якасць прайгравання"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Выбраць аўдыякодэк Bluetooth Audio 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_verbose_logging_summary" msgid="6615071616111731958">"Падвыс. узровень дэтал-цыі журнала Wi‑Fi у залежн. ад SSID RSSI у Wi‑Fi Picker"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Калі ўкл., прылада будзе больш інтэнсіўна імкнуцца перайсці з падлуч. да Wi-Fi на падлуч. да маб. сеткі, калі сігнал Wi‑Fi слабы"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Даведка і водгукі"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Меню"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Каб выканаць скід да заводскіх налад у дэманстрацыйным рэжыме, увядзіце пароль"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Далей"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Патрабуецца пароль"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml
index c97e5f5..4ada334 100644
--- a/packages/SettingsLib/res/values-bg/arrays.xml
+++ b/packages/SettingsLib/res/values-bg/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"Да се използва проверка с HDCP само за DRM съдържание"</item>
     <item msgid="45075631231212732">"Винаги да се използва проверка с HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Използване на сист. избор (стандартно)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Използване на сист. избор (стандартно)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Използване на сист. избор (стандартно)"</item>
+    <item msgid="8895532488906185219">"44,1 кХц"</item>
+    <item msgid="2909915718994807056">"48 кХц"</item>
+    <item msgid="3347287377354164611">"88,2 кХц"</item>
+    <item msgid="1234212100239985373">"96 кХц"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Използване на сист. избор (стандартно)"</item>
+    <item msgid="4482862757811638365">"44,1 кХц"</item>
+    <item msgid="354495328188724404">"48 кХц"</item>
+    <item msgid="7329816882213695083">"88,2 кХц"</item>
+    <item msgid="6967397666254430476">"96 кХц"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Използване на сист. избор (стандартно)"</item>
+    <item msgid="5618929009984956469">"16 бита/дискрет"</item>
+    <item msgid="3412640499234627248">"24 бита/дискрет"</item>
+    <item msgid="121583001492929387">"32 бита/дискрет"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Използване на сист. избор (стандартно)"</item>
+    <item msgid="4726688794884191540">"16 бита/дискрет"</item>
+    <item msgid="305344756485516870">"24 бита/дискрет"</item>
+    <item msgid="244568657919675099">"32 бита/дискрет"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Използване на сист. избор (стандартно)"</item>
+    <item msgid="4106832974775067314">"Моно"</item>
+    <item msgid="5571632958424639155">"Стерео"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Използване на сист. избор (стандартно)"</item>
+    <item msgid="8900559293912978337">"Моно"</item>
+    <item msgid="8883739882299884241">"Стерео"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Оптимизиране за качество на звука (990 или 909 кб/сек)"</item>
+    <item msgid="2921767058740704969">"Балансирано качество на звука и връзката (660 или 606 кб/сек)"</item>
+    <item msgid="3682554248829489641">"Оптимизиране за качество на връзката (330 или 303 кб/сек)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Оптимизиране за качество на звука"</item>
+    <item msgid="4327143584633311908">"Балансирано качество на звука и връзката"</item>
+    <item msgid="6155648878105378550">"Оптимизиране за качество на връзката"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Изключено"</item>
     <item msgid="1593289376502312923">"64 КБ"</item>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index c0d43b2..351b489 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Винаги активни клетъчни данни"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Деактивиране на пълната сила на звука"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Аудиокодек за Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Изберете аудиокодек за Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Честота на дискретизация за звука през Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Изберете аудиокодек за Bluetooth:\nЧестота на дискретизация"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Битове на дискрет за звука през Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Изберете аудиокодек за Bluetooth:\nБитове на дискрет"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Режим на канала на звука през Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Изберете аудиокодек за Bluetooth:\nРежим на канала"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Кодек за звука през Bluetooth с технологията LDAC: Качество на възпроизвеждане"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Изберете кодек за звука през Bluetooth с технологията 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_verbose_logging_summary" msgid="6615071616111731958">"По-подробно регистр. на Wi‑Fi – данни за RSSI на SSID в инстр. за избор на Wi‑Fi"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"При активиране предаването на връзката за данни от Wi-Fi към мобилната мрежа ще е по-агресивно, когато Wi-Fi сигналът е слаб"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Помощ и отзиви"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Меню"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"Средно време по Гринуич (GMT)"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Въведете парола за възст. на фабр. настройки в демонстр. режим"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Напред"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Изисква се парола"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml
index faea551..d558127 100644
--- a/packages/SettingsLib/res/values-bn/arrays.xml
+++ b/packages/SettingsLib/res/values-bn/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"শুধুমাত্র DRM সামগ্রীর জন্য HDCP চেক করা ব্যবহার করুন"</item>
     <item msgid="45075631231212732">"সর্বদা HDCP পরীক্ষণ ব্যবহার করুন"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
+    <item msgid="8895532488906185219">"৪৪.১ kHz"</item>
+    <item msgid="2909915718994807056">"৪৮.০ kHz"</item>
+    <item msgid="3347287377354164611">"৮৮.২ kHz"</item>
+    <item msgid="1234212100239985373">"৯৬.০ kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
+    <item msgid="4482862757811638365">"৪৪.১ kHz"</item>
+    <item msgid="354495328188724404">"৪৮.০ kHz"</item>
+    <item msgid="7329816882213695083">"৮৮.২ kHz"</item>
+    <item msgid="6967397666254430476">"৯৬.০ kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
+    <item msgid="5618929009984956469">"১৬ বিট/নমুনা"</item>
+    <item msgid="3412640499234627248">"২৪ বিট/নমুনা"</item>
+    <item msgid="121583001492929387">"৩২ বিট/নমুনা"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
+    <item msgid="4726688794884191540">"১৬ বিট/নমুনা"</item>
+    <item msgid="305344756485516870">"২৪ বিট/নমুনা"</item>
+    <item msgid="244568657919675099">"৩২ বিট/নমুনা"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
+    <item msgid="4106832974775067314">"মোনো"</item>
+    <item msgid="5571632958424639155">"স্টিরিও"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"সিস্টেমের নির্বাচন ব্যবহার করুন (ডিফল্ট)"</item>
+    <item msgid="8900559293912978337">"মোনো"</item>
+    <item msgid="8883739882299884241">"স্টিরিও"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"অডিওর গুণমানের জন্য অপটিমাইজ করুন (990kbps/909kbps)"</item>
+    <item msgid="2921767058740704969">"সন্তুলিত গুণমানের অডিও এবং সংযোগ (660kbps/606kbps)"</item>
+    <item msgid="3682554248829489641">"সংযোগের গুণমানের জন্য অপটিমাইজ করুন (330kbps/303kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"অডিওর গুণমানের জন্য অপটিমাইজ করুন"</item>
+    <item msgid="4327143584633311908">"সন্তুলিত গুণমানের অডিও এবং সংযোগ"</item>
+    <item msgid="6155648878105378550">"সংযোগের গুণমানের জন্য অপটিমাইজ করুন"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"বন্ধ আছে"</item>
     <item msgid="1593289376502312923">"৬৪K"</item>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 380ee1c..f445e8f 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"সেলুলার ডেটা সর্বদাই সক্রিয় থাকে"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"চূড়ান্ত ভলিউম অক্ষম করুন"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ব্লুটুথ অডিও কোডেক"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"ব্লুটুথ অডিও কোডেক বেছে নিন"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"ব্লুটুথ অডিওর নমুনা হার"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"ব্লুটুথ অডিও কোডেক বেছে নিন:\nস্যাম্পল রেট"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"নমুনা প্রতি ব্লুটুথ অডিও বিট"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"ব্লুটুথ অডিও কোডেক বেছে নিন:\nবিটস পার স্যাম্পল"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"ব্লুটুথ অডিও চ্যানেল মোড"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"ব্লুটুথ অডিও কোডেক বেছে নিন:\nচ্যানেল মোড"</string>
+    <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_verbose_logging_summary" msgid="6615071616111731958">"ওয়াই-ফাই লগিং স্তর বাড়ান, ওয়াই-ফাই চয়নকারীতে SSID RSSI অনুযায়ী দেখান"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"সক্ষম করা থাকলে, নিম্নমানের ওয়াই-ফাই সিগন্যালের ক্ষেত্রে, সেলুলার-এ ডেটা সংযোগ প্রদান করতে ওয়াই-ফাই আরো বেশি শক্তিশালীভাবে কাজ করবে"</string>
@@ -360,4 +353,10 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"সহায়তা ও মতামত"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"মেনু"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <!-- no translation found for retail_demo_reset_message (118771671364131297) -->
+    <skip />
+    <!-- no translation found for retail_demo_reset_next (8356731459226304963) -->
+    <skip />
+    <!-- no translation found for retail_demo_reset_title (696589204029930100) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index 6c4cde3..d9c10f8 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Koristi odabir sistema (Zadano)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Koristi odabir sistema (Zadano)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Koristi odabir sistema (Zadano)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48,0 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Koristi odabir sistema (Zadano)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48,0 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Koristi odabir sistema (Zadano)"</item>
+    <item msgid="5618929009984956469">"16 bitova/uzorak"</item>
+    <item msgid="3412640499234627248">"24 bitova/uzorak"</item>
+    <item msgid="121583001492929387">"32 bitova/uzorak"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Koristi odabir sistema (Zadano)"</item>
+    <item msgid="4726688794884191540">"16 bitova/uzorak"</item>
+    <item msgid="305344756485516870">"24 bitova/uzorak"</item>
+    <item msgid="244568657919675099">"32 bitova/uzorak"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Koristi odabir sistema (Zadano)"</item>
+    <item msgid="4106832974775067314">"Mono"</item>
+    <item msgid="5571632958424639155">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Koristi odabir sistema (Zadano)"</item>
+    <item msgid="8900559293912978337">"Mono"</item>
+    <item msgid="8883739882299884241">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Optimiziraj za kvalitet zvuka (990kbps/909kbps)"</item>
+    <item msgid="2921767058740704969">"Uravnotežen kvalitet zvuka i veze (660kbps/606kbps)"</item>
+    <item msgid="3682554248829489641">"Optimiziraj za kvalitet veze (330kbps/303kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Optimiziraj za kvalitet zvuka"</item>
+    <item msgid="4327143584633311908">"Uravnotežen kvalitet zvuka i veze"</item>
+    <item msgid="6155648878105378550">"Optimiziraj za kvalitet veze"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Isključeno"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index bb0e1b5..aaf9713 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Mobilni podaci uvijek aktivni"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogućite apsolutnu jačinu zvuka"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio kodek"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Odaberite Bluetooth Audio kodek"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Brzina uzorkovanja za Bluetooth audio"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Odaberite Bluetooth Audio kodek:\nBrzina uzorka"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bluetooth audio bitovi po uzorku"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Odaberite Bluetooth Audio kodek:\nBita po uzorku"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Način Bluetooth audio kanala"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Odaberite Bluetooth Audio kodek:\nNačin rada kanala"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth Audio LDAC kodek: Kvalitet reprodukcije"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Odaberite Bluetooth Audio LDAC kodek:\nKvalitet reprodukcije"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Prijenos: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaži opcije za certifikaciju Bežičnog prikaza"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećajte nivo Wi-Fi zapisivanja, pokazati po SSID RSSI Wi-Fi Picker"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Kada je omogućeno, Wi-Fi će biti agresivniji u predavanju podatkovne veze mobilnoj, kada je Wi-Fi signal slab"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Pomoć i povratne informacije"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meni"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Unesite lozinku da izvršite vraćanje na fabričke postavke u načinu demonstracije"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Naprijed"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Potrebna je lozinka"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml
index fb57ab4..5c8c4d7 100644
--- a/packages/SettingsLib/res/values-ca/arrays.xml
+++ b/packages/SettingsLib/res/values-ca/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Selecció del sistema (predeterminada)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Selecció del sistema (predeterminada)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Selecció del sistema (predeterminada)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48,0 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Selecció del sistema (predeterminada)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48,0 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Selecció del sistema (predeterminada)"</item>
+    <item msgid="5618929009984956469">"16 bits/mostra"</item>
+    <item msgid="3412640499234627248">"24 bits/mostra"</item>
+    <item msgid="121583001492929387">"32 bits/mostra"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Selecció del sistema (predeterminada)"</item>
+    <item msgid="4726688794884191540">"16 bits/mostra"</item>
+    <item msgid="305344756485516870">"24 bits/mostra"</item>
+    <item msgid="244568657919675099">"32 bits/mostra"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Selecció del sistema (predeterminada)"</item>
+    <item msgid="4106832974775067314">"Mono"</item>
+    <item msgid="5571632958424639155">"Estèreo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Selecció del sistema (predeterminada)"</item>
+    <item msgid="8900559293912978337">"Mono"</item>
+    <item msgid="8883739882299884241">"Estèreo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Optimitza la qualitat de l\'àudio (990 kbps/909 kbps)"</item>
+    <item msgid="2921767058740704969">"Qualitat equilibrada de l\'àudio i la connexió (660 kbps/606 kbps)"</item>
+    <item msgid="3682554248829489641">"Optimitza la qualitat de la connexió (330 kbps/303 kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Optimitza la qualitat de l\'àudio"</item>
+    <item msgid="4327143584633311908">"Qualitat equilibrada de l\'àudio i la connexió"</item>
+    <item msgid="6155648878105378550">"Optimitza la qualitat de la connexió"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"No"</item>
     <item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 4571e49..391782b 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Dades mòbils sempre actives"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desactiva el volum absolut"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Còdec d\'àudio per Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Selecciona el còdec d\'àudio per Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Velocitat de mostra d’àudio per Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Selecciona el còdec d\'àudio per Bluetooth:\nFreqüència de mostratge"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bits per mostra de l\'àudio per Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Selecciona el còdec d\'àudio per Bluetooth:\nBits per mostra"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Mode de canal de l\'àudio per Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Selecciona el còdec d\'àudio per Bluetooth:\nMode de canal"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Còdec LDAC d\'àudio per Bluetooth: qualitat de reproducció"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Selecciona el còdec LDAC d\'àudio per Bluetooth:\nQualitat de reproducció"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"S\'està reproduint en temps real: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra les opcions de certificació de pantalla sense fil"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Augmenta nivell de registre Wi‑Fi i mostra\'l per SSID RSSI al Selector de Wi‑Fi"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Si s\'activa, la Wi-Fi serà més agressiva en transferir la connexió de dades al mòbil, si el senyal de la Wi-Fi no és estable"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Ajuda i suggeriments"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menú"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Introdueix la contrasenya per restablir les dades de fàbrica en mode de demostració"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Següent"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Contrasenya obligatòria"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 36017e2..ee318ad 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Nápověda a zpětná vazba"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Nabídka"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Chcete-li v ukázkovém režimu obnovit zařízení do továrního nastavení, zadejte heslo"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Další"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Je třeba zadat heslo"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 2824b81..3cd0a6b 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Hjælp og feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Angiv adgangskode for at gendanne fabriksdata i demotilstand"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Næste"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Du skal angive en adgangskode"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-de/arrays.xml b/packages/SettingsLib/res/values-de/arrays.xml
index 796e58f..dec52b2 100644
--- a/packages/SettingsLib/res/values-de/arrays.xml
+++ b/packages/SettingsLib/res/values-de/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Systemauswahl verwenden (Standard)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Systemauswahl verwenden (Standard)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Systemauswahl verwenden (Standard)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Systemauswahl verwenden (Standard)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Systemauswahl verwenden (Standard)"</item>
+    <item msgid="5618929009984956469">"16 Bits pro Sample"</item>
+    <item msgid="3412640499234627248">"24 Bits pro Sample"</item>
+    <item msgid="121583001492929387">"32 Bits pro Sample"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Systemauswahl verwenden (Standard)"</item>
+    <item msgid="4726688794884191540">"16 Bits pro Sample"</item>
+    <item msgid="305344756485516870">"24 Bits pro Sample"</item>
+    <item msgid="244568657919675099">"32 Bits pro Sample"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Systemauswahl verwenden (Standard)"</item>
+    <item msgid="4106832974775067314">"Mono"</item>
+    <item msgid="5571632958424639155">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Systemauswahl verwenden (Standard)"</item>
+    <item msgid="8900559293912978337">"Mono"</item>
+    <item msgid="8883739882299884241">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Für Audioqualität optimieren (990 kbit/s/909 kbit/s)"</item>
+    <item msgid="2921767058740704969">"Ausgeglichene Audio- und Verbindungsqualität (660 kbit/s/606 kbit/s)"</item>
+    <item msgid="3682554248829489641">"Für Verbindungsqualität optimieren (330 kbit/s/303 kbit/s)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Für Audioqualität optimieren"</item>
+    <item msgid="4327143584633311908">"Ausgeglichene Audio- und Verbindungsqualität"</item>
+    <item msgid="6155648878105378550">"Für Verbindungsqualität optimieren"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Aus"</item>
     <item msgid="1593289376502312923">"64.000"</item>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 632866e..8dd4c1db 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Mobile Datennutzung immer aktiviert"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Maximallautstärke deaktivieren"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth-Audio-Codec"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Bluetooth-Audio-Codec auswählen"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bluetooth-Audio-Abtastrate"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Bluetooth-Audio-Codec auswählen:\nAbtastrate"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bluetooth-Audio/Bits pro Sample"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Bluetooth-Audio-Codec auswählen:\nBits pro Sample"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Modus des Bluetooth-Audiokanals"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Bluetooth-Audio-Codec auswählen:\nKanalmodus"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth-Audio-LDAC-Codec: Wiedergabequalität"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Bluetooth-Audio-LDAC-Codec auswählen:\nWiedergabequalität"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streaming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Optionen zur Zertifizierung für kabellose Übertragung anzeigen"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Level für WLAN-Protokollierung erhöhen, in WiFi Picker pro SSID-RSSI anzeigen"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Wenn diese Option aktiviert ist, ist WLAN bei schwachem Signal bei der Übergabe der Datenverbindung an den Mobilfunk aggressiver."</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Hilfe &amp; Feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menü"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Passwort eingeben, um Gerät im Demomodus auf Werkseinstellungen zurückzusetzen"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Weiter"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Passwort erforderlich"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-el/arrays.xml b/packages/SettingsLib/res/values-el/arrays.xml
index 857420c..12a05b9 100644
--- a/packages/SettingsLib/res/values-el/arrays.xml
+++ b/packages/SettingsLib/res/values-el/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"Χρήση ελέγχου HDCP μόνο για περιεχόμενο DRM"</item>
     <item msgid="45075631231212732">"Να χρησιμοποιείται πάντα έλεγχος HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48,0 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48,0 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item>
+    <item msgid="5618929009984956469">"16 bit/δείγμα"</item>
+    <item msgid="3412640499234627248">"24 bit/δείγμα"</item>
+    <item msgid="121583001492929387">"32 bit/δείγμα"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item>
+    <item msgid="4726688794884191540">"16 bit/δείγμα"</item>
+    <item msgid="305344756485516870">"24 bit/δείγμα"</item>
+    <item msgid="244568657919675099">"32 bit/δείγμα"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item>
+    <item msgid="4106832974775067314">"Μονοφωνικό"</item>
+    <item msgid="5571632958424639155">"Στερεοφωνικό"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Χρήση επιλογής συστήματος (Προεπιλογή)"</item>
+    <item msgid="8900559293912978337">"Μονοφωνικό"</item>
+    <item msgid="8883739882299884241">"Στερεοφωνικό"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Βελτιστοποίηση για ποιότητα ήχου (990kbps/909kbps)"</item>
+    <item msgid="2921767058740704969">"Ισορροπημένος ήχος και ποιότητα σύνδεσης (660kbps/606kbps)"</item>
+    <item msgid="3682554248829489641">"Βελτιστοποίηση για ποιότητα σύνδεσης (330kbps/303kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Βελτιστοποίηση για ποιότητα ήχου"</item>
+    <item msgid="4327143584633311908">"Ισορροπημένος ήχος και ποιότητα σύνδεσης"</item>
+    <item msgid="6155648878105378550">"Βελτιστοποίηση για ποιότητα σύνδεσης"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Ανενεργό"</item>
     <item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 67365a3..1ee6db8 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Πάντα ενεργά δεδομένα κινητής τηλεφωνίας"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Απενεργοποίηση απόλυτης έντασης"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Κωδικοποιητής ήχου Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Επιλογή κωδικοποιητή ήχου Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Ρυθμός δειγματοληψίας ήχου Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Επιλογή κωδικοποιητή ήχου Bluetooth:\nΠοσοστό δείγματος"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bit ανά δείγμα ήχου Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Επιλογή κωδικοποιητή ήχου Bluetooth:\nBit ανά δείγμα"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Λειτουργία καναλιού ήχου Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Επιλογή κωδικοποιητή ήχου Bluetooth:\nΛειτουργία καναλιού"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Κωδικοποιητής LDAC ήχου Bluetooth: Ποιότητα αναπαραγωγής"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Επιλογή κωδικοποιητή LDAC ήχου Bluetooth:\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_verbose_logging_summary" msgid="6615071616111731958">"Αύξηση επιπέδου καταγ. Wi-Fi, εμφάνιση ανά SSID RSSI στο εργαλείο επιλογής Wi-Fi"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Όταν είναι ενεργό, το Wi-Fi θα μεταβιβάζει πιο επιθετικά τη σύνδ.δεδομένων σε δίκτυο κινητής τηλ., όταν το σήμα Wi-Fi είναι χαμηλό"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Βοήθεια και σχόλια"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Μενού"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Εισαγάγετε κωδικό πρόσβασης για επαναφορά εργοστασιακών ρυθμίσεων στη λειτουργία επίδειξης"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Επόμενο"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Απαιτείται κωδικός πρόσβασης"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index bb8fc15..af9895e 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Help &amp; feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Enter password to perform factory reset in demo mode"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Next"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Password required"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index bb8fc15..af9895e 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Help &amp; feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Enter password to perform factory reset in demo mode"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Next"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Password required"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index bb8fc15..af9895e 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Help &amp; feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Enter password to perform factory reset in demo mode"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Next"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Password required"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml
index 4df4952..09480a5 100644
--- a/packages/SettingsLib/res/values-es-rUS/arrays.xml
+++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Usar selección del sistema (predeterminado)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Usar selección del sistema (predeterminado)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Usar selección del sistema (predeterminado)"</item>
+    <item msgid="8895532488906185219">"44.1 kHz"</item>
+    <item msgid="2909915718994807056">"48.0 kHz"</item>
+    <item msgid="3347287377354164611">"88.2 kHz"</item>
+    <item msgid="1234212100239985373">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Usar selección del sistema (predeterminado)"</item>
+    <item msgid="4482862757811638365">"44.1 kHz"</item>
+    <item msgid="354495328188724404">"48.0 kHz"</item>
+    <item msgid="7329816882213695083">"88.2 kHz"</item>
+    <item msgid="6967397666254430476">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Usar selección del sistema (predeterminado)"</item>
+    <item msgid="5618929009984956469">"16 bits/muestra"</item>
+    <item msgid="3412640499234627248">"24 bits/muestra"</item>
+    <item msgid="121583001492929387">"32 bits/muestra"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Usar selección del sistema (predeterminado)"</item>
+    <item msgid="4726688794884191540">"16 bits/muestra"</item>
+    <item msgid="305344756485516870">"24 bits/muestra"</item>
+    <item msgid="244568657919675099">"32 bits/muestra"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Usar selección del sistema (predeterminado)"</item>
+    <item msgid="4106832974775067314">"Mono"</item>
+    <item msgid="5571632958424639155">"Estéreo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Usar selección del sistema (predeterminado)"</item>
+    <item msgid="8900559293912978337">"Mono"</item>
+    <item msgid="8883739882299884241">"Estéreo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Optimizar para calidad de audio (990 kbps/909 kbps)"</item>
+    <item msgid="2921767058740704969">"Calidad de audio y conexión equilibrada (660 kbps/606 kbps)"</item>
+    <item msgid="3682554248829489641">"Optimizar para calidad de conexión (330 kbps/303 kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Optimizar para la calidad de audio"</item>
+    <item msgid="4327143584633311908">"Calidad de audio y conexión equilibrada"</item>
+    <item msgid="6155648878105378550">"Optimizar para calidad de conexión"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Desactivado"</item>
     <item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 9d9a087..25ee5a8 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Datos móviles siempre activos"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Inhabilitar volumen absoluto"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Códec del audio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Seleccionar códec del audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Frecuencia de muestreo del audio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Seleccionar códec del audio Bluetooth:\nVelocidad de la muestra"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bits por muestra del audio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Seleccionar códec del audio Bluetooth:\nBits por muestra"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Modo de canal del audio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Seleccionar códec del audio Bluetooth:\nModo de canal"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Códec del audio Bluetooth LDAC: calidad de reproducción"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Seleccionar códec del audio Bluetooth LDAC:\nCalidad de reproducción"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Transmitiendo: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opciones de certificación de pantalla inalámbrica"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar nivel de registro Wi-Fi; mostrar por SSID RSSI en el selector de Wi-Fi"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Si está habilitada, la conexión Wi‑Fi será más intensa al transferir la conexión de datos al celular (si la señal Wi‑Fi es débil)."</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Ayuda y comentarios"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menú"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Ingresa contraseña y restablece en demo"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Siguiente"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Contraseña obligatoria"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml
index bf492c7..b5160a4 100644
--- a/packages/SettingsLib/res/values-es/arrays.xml
+++ b/packages/SettingsLib/res/values-es/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Usar preferencia del sistema (predeter.)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Usar preferencia del sistema (predeter.)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Usar preferencia del sistema (predeter.)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Usar preferencia del sistema (predeter.)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Usar preferencia del sistema (predeter.)"</item>
+    <item msgid="5618929009984956469">"16 bits por muestra"</item>
+    <item msgid="3412640499234627248">"24 bits por muestra"</item>
+    <item msgid="121583001492929387">"32 bits por muestra"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Usar preferencia del sistema (predeter.)"</item>
+    <item msgid="4726688794884191540">"16 bits por muestra"</item>
+    <item msgid="305344756485516870">"24 bits por muestra"</item>
+    <item msgid="244568657919675099">"32 bits por muestra"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Usar preferencia del sistema (predeter.)"</item>
+    <item msgid="4106832974775067314">"Mono"</item>
+    <item msgid="5571632958424639155">"Estéreo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Usar preferencia del sistema (predeter.)"</item>
+    <item msgid="8900559293912978337">"Mono"</item>
+    <item msgid="8883739882299884241">"Estéreo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Optimizar la calidad del audio (990/909&amp;nbsp;kbps)"</item>
+    <item msgid="2921767058740704969">"Equilibrar la calidad del audio y de la conexión (660/606&amp;nbsp;kbps)"</item>
+    <item msgid="3682554248829489641">"Optimizar la calidad de la conexión (330/303&amp;nbsp;kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Optimizar la calidad del audio"</item>
+    <item msgid="4327143584633311908">"Equilibrar la calidad del audio y la de la conexión"</item>
+    <item msgid="6155648878105378550">"Optimizar la calidad de la conexión"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"No"</item>
     <item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 2e4be1c..9d98096 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Datos móviles siempre activos"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Inhabilitar volumen absoluto"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Códec de audio por Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Selecciona el códec de audio por Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Porcentaje de muestreo de audio por Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Selecciona el códec de audio por Bluetooth:\nFrecuencia de muestreo"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bits de audio por Bluetooth por muestra"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Selecciona el códec de audio por Bluetooth:\nBits por muestra"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Modo de canal de audio por Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Selecciona el códec de audio por Bluetooth:\nModo de canal"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Selecciona el códec LDAC por Bluetooth: calidad de reproducción"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Selecciona el códec LDAC de audio por Bluetooth:\nCalidad de reproducción"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streaming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opciones para la certificación de la pantalla inalámbrica"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar el nivel de logging de Wi-Fi, mostrar por SSID RSSI en el selector Wi-Fi"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Si está habilitada, la conexión Wi‑Fi será más agresiva al transferir la conexión de datos al móvil (si la señal Wi‑Fi no es estable)"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Ayuda y sugerencias"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menú"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Escribe una contraseña para restablecer datos de fábrica en modo demostración"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Siguiente"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Contraseña obligatoria"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-et/arrays.xml b/packages/SettingsLib/res/values-et/arrays.xml
index ca60dfa..f26543e 100644
--- a/packages/SettingsLib/res/values-et/arrays.xml
+++ b/packages/SettingsLib/res/values-et/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Süsteemi valiku kasutamine (vaikeseade)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Süsteemi valiku kasutamine (vaikeseade)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Süsteemi valiku kasutamine (vaikeseade)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48,0 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Süsteemi valiku kasutamine (vaikeseade)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48,0 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Süsteemi valiku kasutamine (vaikeseade)"</item>
+    <item msgid="5618929009984956469">"16 bitti diskreedi kohta"</item>
+    <item msgid="3412640499234627248">"24 bitti diskreedi kohta"</item>
+    <item msgid="121583001492929387">"32 bitti diskreedi kohta"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Süsteemi valiku kasutamine (vaikeseade)"</item>
+    <item msgid="4726688794884191540">"16 bitti diskreedi kohta"</item>
+    <item msgid="305344756485516870">"24 bitti diskreedi kohta"</item>
+    <item msgid="244568657919675099">"32 bitti diskreedi kohta"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Süsteemi valiku kasutamine (vaikeseade)"</item>
+    <item msgid="4106832974775067314">"Mono"</item>
+    <item msgid="5571632958424639155">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Süsteemi valiku kasutamine (vaikeseade)"</item>
+    <item msgid="8900559293912978337">"Mono"</item>
+    <item msgid="8883739882299884241">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Helikvaliteedi jaoks optimeerimine (990/909 kbit/s)"</item>
+    <item msgid="2921767058740704969">"Tasakaalustatud heli- ja ühenduskvaliteet (660/606 kbit/s)"</item>
+    <item msgid="3682554248829489641">"Ühenduskvaliteedi jaoks optimeerimine (330/303 kbit/s)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Helikvaliteedi jaoks optimeerimine"</item>
+    <item msgid="4327143584633311908">"Tasakaalustatud heli- ja ühenduskvaliteet"</item>
+    <item msgid="6155648878105378550">"Ühenduskvaliteedi jaoks optimeerimine"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Väljas"</item>
     <item msgid="1593289376502312923">"64 000"</item>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index c51e2eb..507bd20 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Mobiilne andmeside on alati aktiivne"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Keela absoluutne helitugevus"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetoothi heli kodek"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Valige Bluetoothi helikodek"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bluetoothi heli diskreetimissagedus"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Valige Bluetoothi helikodek:\ndiskreetimissagedus"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bluetoothi heli bitte diskreedi kohta"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Valige Bluetoothi helikodek:\nbitte diskreetimise kohta"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Bluetoothi heli kanalirežiim"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Valige Bluetoothi helikodek:\nkanalirežiim"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetoothi LDAC-helikodek: taasesituskvaliteet"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Valige Bluetoothi LDAC-helikodek:\ntaasesituskvaliteet"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Voogesitus: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Juhtmeta ekraaniühenduse sertifitseerimisvalikute kuvamine"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Suurenda WiFi logimistaset, kuva WiFi valijas SSID RSSI järgi"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Kui see on lubatud, siis püüab WiFi nõrga WiFi-signaali korral agressiivsemalt anda andmeside ühenduse üle mobiilsele andmesidele"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Abi ja tagasiside"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menüü"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Sisestage parool, et demorežiimis tehaseseadetele lähtestada"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Järgmine"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Parool on kohustuslik"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml
index 807d562..4c4e7e7 100644
--- a/packages/SettingsLib/res/values-eu/arrays.xml
+++ b/packages/SettingsLib/res/values-eu/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"Erabili HDCP egiaztapena DRM edukirako soilik"</item>
     <item msgid="45075631231212732">"Erabili beti HDCP egiaztapena"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Erabili sistema-hautapena (lehenetsia)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Erabili sistema-hautapena (lehenetsia)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Erabili sistema-hautapena (lehenetsia)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48,0 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Erabili sistema-hautapena (lehenetsia)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48,0 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Erabili sistema-hautapena (lehenetsia)"</item>
+    <item msgid="5618929009984956469">"16 bit lagin bakoitzeko"</item>
+    <item msgid="3412640499234627248">"24 bit lagin bakoitzeko"</item>
+    <item msgid="121583001492929387">"32 bit lagin bakoitzeko"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Erabili sistema-hautapena (lehenetsia)"</item>
+    <item msgid="4726688794884191540">"16 bit lagin bakoitzeko"</item>
+    <item msgid="305344756485516870">"24 bit lagin bakoitzeko"</item>
+    <item msgid="244568657919675099">"32 bit lagin bakoitzeko"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Erabili sistema-hautapena (lehenetsia)"</item>
+    <item msgid="4106832974775067314">"Monoa"</item>
+    <item msgid="5571632958424639155">"Estereoa"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Erabili sistema-hautapena (lehenetsia)"</item>
+    <item msgid="8900559293912978337">"Monoa"</item>
+    <item msgid="8883739882299884241">"Estereoa"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Optimizatu audioaren kalitatea areagotzeko (990 kbps / 909kbps)"</item>
+    <item msgid="2921767058740704969">"Orekatu audioaren eta konexioaren kalitateak (660 kbps / 606 kbps)"</item>
+    <item msgid="3682554248829489641">"Optimizatu konexioaren kalitatea areagotzeko (330 kbps / 303 kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Optimizatu audioaren kalitatea areagotzeko"</item>
+    <item msgid="4327143584633311908">"Orekatu audioaren eta konexioaren kalitateak"</item>
+    <item msgid="6155648878105378550">"Optimizatu konexioaren kalitatea areagotzeko"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Desaktibatuta"</item>
     <item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 98177d2f..d8b2496 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Mugikorreko datuak beti aktibo"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desgaitu bolumen absolutua"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth bidezko audioaren kodeka"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Hautatu Bluetooth audioaren kodeka"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bluetooth bidezko audioaren lagin-abiadura"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Hautatu Bluetooth audioaren LDAC kodeka:\nlaginaren abiadura"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bluetooth bidezko audioaren lagin bakoitzeko bit kopurua"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Hautatu Bluetooth audioaren kodeka:\nlagin bakoitzeko bitak"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Bluetooth bidezko audioaren kanalaren modua"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Hautatu Bluetooth audioaren kodeka:\nkanal modua"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth audioaren LDAC kodeka: erreprodukzioaren kalitatea"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Hautatu Bluetooth audioaren LDAC kodeka:\nerreprodukzioaren kalitatea"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Igortzean: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Erakutsi hari gabeko bistaratze-egiaztapenaren aukerak"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Erakutsi datu gehiago Wi-Fi sareetan saioa hasterakoan. Erakutsi sarearen identifikatzailea eta seinalearen indarra Wi‑Fi sareen hautagailuan."</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Aukera hori gaituz gero, gailua errazago aldatuko da datu mugikorren konexiora Wi-Fi seinalea ahultzen dela nabaritutakoan"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Laguntza eta iritziak"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menua"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Idatzi pasahitza jatorrizko ezarpenak demo moduan berrezartzeko"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Hurrengoa"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Pasahitza behar da"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 9f0b639..61ec98e 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"راهنما و بازخورد"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"منو"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"برای انجام بازنشانی کارخانه‌ای در حالت نمایشی، گذرواژه را وارد کنید"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"بعدی"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"وارد کردن گذرواژه الزامی است"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 7f78001..a954b17 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Ohje ja palaute"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Valikko"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Palauta tehdasasetukset antamalla salasana"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Seuraava"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Salasana vaaditaan"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index cd0ab25..973458d 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Aide et commentaires"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Entrez m. passe pour réinit. en mode démo"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Suivant"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Mot de passe obligatoire"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 8587e28..9ce3d5a 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Aide et commentaires"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Saisir mot de passe pour rétablir conf. d\'usine en mode démo."</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Suivant"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Veuillez saisir le mot de passe"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 6820575..dfdb851 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Axuda e suxestións"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menú"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Insire contrasinal para restablec. en demostración"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Seguinte"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"O contrasinal é obrigatorio"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml
index d41cfbc..e00c29f 100644
--- a/packages/SettingsLib/res/values-gu/arrays.xml
+++ b/packages/SettingsLib/res/values-gu/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"ફક્ત DRM સામગ્રી માટે HDCP તપાસનો ઉપયોગ કરો"</item>
     <item msgid="45075631231212732">"હંમેશા HDCP તપાસનો ઉપયોગ કરો"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
+    <item msgid="8895532488906185219">"44.1 kHz"</item>
+    <item msgid="2909915718994807056">"48.0 kHz"</item>
+    <item msgid="3347287377354164611">"88.2 kHz"</item>
+    <item msgid="1234212100239985373">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
+    <item msgid="4482862757811638365">"44.1 kHz"</item>
+    <item msgid="354495328188724404">"48.0 kHz"</item>
+    <item msgid="7329816882213695083">"88.2 kHz"</item>
+    <item msgid="6967397666254430476">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
+    <item msgid="5618929009984956469">"16 બિટ/નમૂનો"</item>
+    <item msgid="3412640499234627248">"24 બિટ/નમૂનો"</item>
+    <item msgid="121583001492929387">"32 બિટ/નમૂનો"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
+    <item msgid="4726688794884191540">"16 બિટ/નમૂનો"</item>
+    <item msgid="305344756485516870">"24 બિટ/નમૂનો"</item>
+    <item msgid="244568657919675099">"32 બિટ/નમૂનો"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
+    <item msgid="4106832974775067314">"મૉનો"</item>
+    <item msgid="5571632958424639155">"સ્ટીરિઓ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"સિસ્ટમ પસંદગીનો ઉપયોગ કરો (ડિફૉલ્ટ)"</item>
+    <item msgid="8900559293912978337">"મૉનો"</item>
+    <item msgid="8883739882299884241">"સ્ટીરિઓ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"ઑડિઓની ગુણવત્તા માટે ઑપ્ટિમાઇઝ કરો (990kbps/909kbps)"</item>
+    <item msgid="2921767058740704969">"સંતુલિત ઑડિઓ અને કનેક્શનની ગુણવત્તા (660kbps/606kbps)"</item>
+    <item msgid="3682554248829489641">"કનેક્શનની ગુણવત્તા માટે ઑપ્ટિમાઇઝ કરો (330kbps/303kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"ઑડિઓ ગુણવત્તા માટે ઑપ્ટિમાઇઝ કરો"</item>
+    <item msgid="4327143584633311908">"સંતુલિત ઑડિઓ અને કનેક્શનની ગુણવત્તા"</item>
+    <item msgid="6155648878105378550">"કનેક્શનની ગુણવત્તા માટે ઑપ્ટિમાઇઝ કરો"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"બંધ"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 8e68ab0..f6d2327 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"સેલ્યુલર ડેટા હંમેશા સક્રિય"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ચોક્કસ વૉલ્યૂમને અક્ષમ કરો"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth ઑડિઓ કોડેક"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Bluetooth ઑડિઓ LDAC કોડેક પસંદ કરો"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bluetooth ઑડિઓ નમૂના દર"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Bluetooth ઑડિઓ LDAC કોડેક પસંદ કરો:\nનમૂના દર"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"નમૂના દીઠ Bluetooth ઑડિઓ બિટ"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Bluetooth ઑડિઓ કોડેક પસંદ કરો:\nનમૂના દીઠ બિટ"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Bluetooth ઑડિઓ ચેનલ મોડ"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Bluetooth ઑડિઓ કોડેક પસંદ કરો:\nચૅનલ મોડ"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth ઑડિઓ LDAC કોડેક: પ્લેબૅક ગુણવત્તા"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Bluetooth ઑડિઓ 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_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi લોગિંગ સ્તર વધારો, Wi‑Fi પીકરમાં SSID RSSI દીઠ બતાવો"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"જ્યારે સક્ષમ હોય, ત્યારે Wi‑Fi સિગ્નલ ઓછા હોવા પર, સેલ્યુલર પર ડેટા કનેક્શન મોકલવામાં વધુ આક્રમક હશે"</string>
@@ -360,4 +353,10 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"સહાય અને પ્રતિસાદ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"મેનુ"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <!-- no translation found for retail_demo_reset_message (118771671364131297) -->
+    <skip />
+    <!-- no translation found for retail_demo_reset_next (8356731459226304963) -->
+    <skip />
+    <!-- no translation found for retail_demo_reset_title (696589204029930100) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml
index 489e8e7..ecf101a 100644
--- a/packages/SettingsLib/res/values-hi/arrays.xml
+++ b/packages/SettingsLib/res/values-hi/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"HDCP जांच का उपयोग केवल DRM सामग्री के लिए करें"</item>
     <item msgid="45075631231212732">"हमेशा HDCP जांच का उपयोग करें"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item>
+    <item msgid="8895532488906185219">"44.1 kHz"</item>
+    <item msgid="2909915718994807056">"48.0 kHz"</item>
+    <item msgid="3347287377354164611">"88.2 kHz"</item>
+    <item msgid="1234212100239985373">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item>
+    <item msgid="4482862757811638365">"44.1 kHz"</item>
+    <item msgid="354495328188724404">"48.0 kHz"</item>
+    <item msgid="7329816882213695083">"88.2 kHz"</item>
+    <item msgid="6967397666254430476">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item>
+    <item msgid="5618929009984956469">"16 बिट/नमूना"</item>
+    <item msgid="3412640499234627248">"24 बिट/नमूना"</item>
+    <item msgid="121583001492929387">"32 बिट/नमूना"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item>
+    <item msgid="4726688794884191540">"16 बिट/नमूना"</item>
+    <item msgid="305344756485516870">"24 बिट/नमूना"</item>
+    <item msgid="244568657919675099">"32 बिट/नमूना"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item>
+    <item msgid="4106832974775067314">"मोनो"</item>
+    <item msgid="5571632958424639155">"स्टीरियो"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item>
+    <item msgid="8900559293912978337">"मोनो"</item>
+    <item msgid="8883739882299884241">"स्टीरियो"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"ऑडियो गुणवत्ता के अनुसार बदलाव करें (990kbps/909kbps)"</item>
+    <item msgid="2921767058740704969">"संतुलित ऑडियो और कनेक्शन गुणवत्ता (660kbps/606kbps)"</item>
+    <item msgid="3682554248829489641">"कनेक्शन गुणवत्ता के अनुसार बदलाव करें (330kbps/303kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"ऑडियो गुणवत्ता के अनुसार बदलाव करें"</item>
+    <item msgid="4327143584633311908">"संतुलित ऑडियो और कनेक्शन गुणवत्ता"</item>
+    <item msgid="6155648878105378550">"कनेक्शन गुणवत्ता के अनुसार बदलाव करें"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"बंद"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index fd01c6b..f0cb2e3 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"सेल्युलर डेटा हमेशा सक्रिय"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"पूर्ण वॉल्यूम अक्षम करें"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ब्लूटूथ ऑडियो कोडेक"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"ब्लूटूथ ऑडियो कोडेक चुनें"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"ब्लूटूथ ऑडियो नमूना दर"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"ब्लूटूथ ऑडियो कोडेक चुनें:\nनमूना दर"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"ब्लूटूथ ऑडियो बिट प्रति नमूना"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"ब्लूटूथ ऑडियो कोडेक चुनें:\nबिट प्रति नमूना"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"ब्लूटूथ ऑडियो चैनल मोड"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"ब्लूटूथ ऑडियो कोडेक चुनें:\nचैनल मोड"</string>
+    <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_verbose_logging_summary" msgid="6615071616111731958">"वाई-फ़ाई प्रवेश स्तर बढ़ाएं, वाई-फ़ाई पिकर में प्रति SSID RSSI दिखाएं"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"इसके सक्षम होने पर, जब वाई-फ़ाई संकेत कमज़ोर हों तो वाई-फ़ाई, डेटा कनेक्शन को सेल्यूलर पर अधिक बलपूर्वक भेजेगा"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"सहायता और फ़ीडबैक"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"मेनू"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"डेमो मोड में फ़ैक्टरी रीसेट के लिए पासवर्ड डालें"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"आगे"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"पासवर्ड आवश्यक"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hr/arrays.xml b/packages/SettingsLib/res/values-hr/arrays.xml
index 8415bee..2b70c78 100644
--- a/packages/SettingsLib/res/values-hr/arrays.xml
+++ b/packages/SettingsLib/res/values-hr/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Upotreba odabira sustava (zadano)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Upotreba odabira sustava (zadano)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Upotreba odabira sustava (zadano)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48,0 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Upotreba odabira sustava (zadano)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48,0 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Upotreba odabira sustava (zadano)"</item>
+    <item msgid="5618929009984956469">"16 bitova po uzorku"</item>
+    <item msgid="3412640499234627248">"24 bita po uzorku"</item>
+    <item msgid="121583001492929387">"32 bita po uzorku"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Upotreba odabira sustava (zadano)"</item>
+    <item msgid="4726688794884191540">"16 bitova po uzorku"</item>
+    <item msgid="305344756485516870">"24 bita po uzorku"</item>
+    <item msgid="244568657919675099">"32 bita po uzorku"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Upotreba odabira sustava (zadano)"</item>
+    <item msgid="4106832974775067314">"Mono"</item>
+    <item msgid="5571632958424639155">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Upotreba odabira sustava (zadano)"</item>
+    <item msgid="8900559293912978337">"Mono"</item>
+    <item msgid="8883739882299884241">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Optimizacija za kvalitetu audioreprodukcije (990 kbps/909 kbps)"</item>
+    <item msgid="2921767058740704969">"Uravnotežena kvaliteta audioreprodukcije i veze (660 kbps/606 kbps)"</item>
+    <item msgid="3682554248829489641">"Optimizacija za kvalitetu veze (330 kbps/303 kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Optimizacija za kvalitetu audioreprodukcije"</item>
+    <item msgid="4327143584633311908">"Uravnotežena kvaliteta audioreprodukcije i veze"</item>
+    <item msgid="6155648878105378550">"Optimizacija za kvalitetu veze"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Isključeno"</item>
     <item msgid="1593289376502312923">"64 KB"</item>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 21fdce5..4de241a 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Mobilni podaci uvijek aktivni"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Onemogući apsolutnu glasnoću"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Kodek za Bluetooth Audio"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Odaberi kodek za Bluetooth Audio"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Brzina uzorka za Bluetooth Audio"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Odaberi kodek za Bluetooth Audio:\nbrzina uzorkovanja"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bitovi po uzorku za Bluetooth Audio"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Odaberi kodek za Bluetooth Audio:\nbitovi po uzorku"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Način kanala za Bluetooth Audio"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Odaberi kodek za Bluetooth Audio:\nnačin kanala"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Kodek za Bluetooth Audio LDAC: kvaliteta reprodukcije"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Odaberi kodek za Bluetooth Audio LDAC:\nkvaliteta reprodukcije"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Strujanje: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Prikaži opcije za certifikaciju bežičnog prikaza"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećana razina prijave na Wi‑Fi, prikaz po SSID RSSI-ju u Biraču Wi‑Fi-ja"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Ako je omogućeno, Wi-Fi će aktivno prebacivati podatkovnu vezu mobilnoj mreži kada je Wi-Fi signal slab."</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Pomoć i povratne informacije"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Izbornik"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Unesite zaporku za resetiranje u demu"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Dalje"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Potrebna je zaporka"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hu/arrays.xml b/packages/SettingsLib/res/values-hu/arrays.xml
index 9f314ac..99727cc 100644
--- a/packages/SettingsLib/res/values-hu/arrays.xml
+++ b/packages/SettingsLib/res/values-hu/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Rendszerérték (alapértelmezett)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Rendszerérték (alapértelmezett)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Rendszerérték (alapértelmezett)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Rendszerérték (alapértelmezett)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Rendszerérték (alapértelmezett)"</item>
+    <item msgid="5618929009984956469">"16 bit/minta"</item>
+    <item msgid="3412640499234627248">"24 bit/minta"</item>
+    <item msgid="121583001492929387">"32 bit/minta"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Rendszerérték (alapértelmezett)"</item>
+    <item msgid="4726688794884191540">"16 bit/minta"</item>
+    <item msgid="305344756485516870">"24 bit/minta"</item>
+    <item msgid="244568657919675099">"32 bit/minta"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Rendszerérték (alapértelmezett)"</item>
+    <item msgid="4106832974775067314">"Monó"</item>
+    <item msgid="5571632958424639155">"Sztereó"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Rendszerérték (alapértelmezett)"</item>
+    <item msgid="8900559293912978337">"Monó"</item>
+    <item msgid="8883739882299884241">"Sztereó"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Optimalizálás hangminőséghez (990 kbps/909 kbps)"</item>
+    <item msgid="2921767058740704969">"Kiegyensúlyozott hang- és kapcsolatminőség (660 kbps/606 kbps)"</item>
+    <item msgid="3682554248829489641">"Optimalizálás kapcsolatminőséghez (330 kbps/303 kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Optimalizálás hangminőséghez"</item>
+    <item msgid="4327143584633311908">"Kiegyensúlyozott hang- és kapcsolatminőség"</item>
+    <item msgid="6155648878105378550">"Optimalizálás kapcsolatminőséghez"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Ki"</item>
     <item msgid="1593289376502312923">"64 KB"</item>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 63c38d0..15417d6 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"A mobilhálózati adatforgalom mindig aktív"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Abszolút hangerő funkció letiltása"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth hang – Kodek"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Bluetooth hangkodek kiválasztása"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bluetooth hang – mintavételezési gyakoriság"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Bluetooth hangkodek kiválasztása:\nmintavételi gyakoriság"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bluetooth hang – bit/minta"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Bluetooth hangkodek kiválasztása:\nbit/minta"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Bluetooth hang – Csatornamód"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Bluetooth hangkodek kiválasztása:\ncsatornamód"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth LDAC hangkodek: lejátszási minőség"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Bluetooth LDAC hangkodek kiválasztása:\nlejátszási minőség"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streamelés: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vezeték nélküli kijelző tanúsítványával kapcsolatos lehetőségek megjelenítése"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi-naplózási szint növelése, RSSI/SSID megjelenítése a Wi‑Fi-választóban"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Ha engedélyezi, a Wi-Fi agresszívebben fogja átadni az adatkapcsolatot a mobilhálózatnak gyenge Wi-Fi-jel esetén"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Súgó és visszajelzés"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menü"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Írja be a jelszót a visszaállításhoz"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Következő"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Jelszó szükséges"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml
index 057399e..e3b553e 100644
--- a/packages/SettingsLib/res/values-hy/arrays.xml
+++ b/packages/SettingsLib/res/values-hy/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"Օգտագործել HDCP-ը` միայն DRM-ի բովանդակությունը ստուգելու համար"</item>
     <item msgid="45075631231212732">"Միշտ օգտագործել HDCP ստուգումը"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item>
+    <item msgid="8895532488906185219">"44,1 կՀց"</item>
+    <item msgid="2909915718994807056">"48,0 կՀց"</item>
+    <item msgid="3347287377354164611">"88,2 կՀց"</item>
+    <item msgid="1234212100239985373">"96,0 կՀց"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item>
+    <item msgid="4482862757811638365">"44,1 կՀց"</item>
+    <item msgid="354495328188724404">"48,0 կՀց"</item>
+    <item msgid="7329816882213695083">"88,2 կՀց"</item>
+    <item msgid="6967397666254430476">"96,0 կՀց"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item>
+    <item msgid="5618929009984956469">"16 բիթ/նմուշ"</item>
+    <item msgid="3412640499234627248">"24 բիթ/նմուշ"</item>
+    <item msgid="121583001492929387">"32 բիթ/նմուշ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item>
+    <item msgid="4726688794884191540">"16 բիթ/նմուշ"</item>
+    <item msgid="305344756485516870">"24 բիթ/նմուշ"</item>
+    <item msgid="244568657919675099">"32 բիթ/նմուշ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item>
+    <item msgid="4106832974775067314">"Մոնո"</item>
+    <item msgid="5571632958424639155">"Ստերեո"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Օգտագործել համակարգի կարգավորումը (կանխադրված)"</item>
+    <item msgid="8900559293912978337">"Մոնո"</item>
+    <item msgid="8883739882299884241">"Ստերեո"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Օպտիմալացնել ձայնի որակը (990 կբ/վ / 909 կբ/վ)"</item>
+    <item msgid="2921767058740704969">"Ձայնի և կապի հավասարակշռված որակ (660 կբ/վ / 606 կբ/վ)"</item>
+    <item msgid="3682554248829489641">"Օպտիմալացնել կապի որակը (330 կբ/վ / 303 կբ/վ)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Օպտիմալացնել ձայնի որակը"</item>
+    <item msgid="4327143584633311908">"Ձայնի և կապի հավասարակշռված որակ"</item>
+    <item msgid="6155648878105378550">"Օպտիմալացնել կապի որակը"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Անջատված է"</item>
     <item msgid="1593289376502312923">"64ԿԲ"</item>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index b4efac1..c75220f 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Բջջային տվյալները՝ միշտ ակտիվացրած"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Անջատել ձայնի բացարձակ ուժգնությունը"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth աուդիո կոդեկ"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Ընտրեք Bluetooth աուդիո կոդեկը"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bluetooth աուդիոյի Ընդհատավորման հաճախականությունը"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Ընտրեք Bluetooth աուդիո կոդեկը՝\nընդհատավորման հաճախականություն"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bluetooth աուդիո, բիթ / նմուշ"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Ընտրեք Bluetooth աուդիո կոդեկը՝\nբիթ/նմուշ"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Bluetooth աուդիո կապուղու ռեժիմը"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Ընտրեք Bluetooth աուդիո կոդեկը՝\nկապուղու ռեժիմ"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth աուդիո LDAC կոդեկ՝ նվագարկման որակ"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Ընտրեք Bluetooth աուդիո 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_verbose_logging_summary" msgid="6615071616111731958">"Բարձրացնել մակարդակը, Wi‑Fi ընտրիչում ամեն մի SSID-ի համար ցույց տալ RSSI"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Եթե այս գործառույթը միացված է, Wi‑Fi-ի թույլ ազդանշանի դեպքում Wi‑Fi ինտերնետից անցումը բջջային ինտերնետին ավելի կտրուկ կլինի"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Օգնություն և հետադարձ կապ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Ընտրացանկ"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Մուտքագրեք գաղտնաբառը՝ ցուցադրական ռեժիմում գործարանային վերակայում կատարելու համար"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Հաջորդը"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Պահանջվում է գաղտնաբառ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml
index 1ccf993..9d56ba7 100644
--- a/packages/SettingsLib/res/values-in/arrays.xml
+++ b/packages/SettingsLib/res/values-in/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Gunakan Pilihan Sistem (Default)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Gunakan Pilihan Sistem (Default)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Gunakan Pilihan Sistem (Default)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48,0 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Gunakan Pilihan Sistem (Default)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48,0 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Gunakan Pilihan Sistem (Default)"</item>
+    <item msgid="5618929009984956469">"16 bit/sampel"</item>
+    <item msgid="3412640499234627248">"24 bit/sampel"</item>
+    <item msgid="121583001492929387">"32 bit/sampel"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Gunakan Pilihan Sistem (Default)"</item>
+    <item msgid="4726688794884191540">"16 bit/sampel"</item>
+    <item msgid="305344756485516870">"24 bit/sampel"</item>
+    <item msgid="244568657919675099">"32 bit/sampel"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Gunakan Pilihan Sistem (Default)"</item>
+    <item msgid="4106832974775067314">"Mono"</item>
+    <item msgid="5571632958424639155">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Gunakan Pilihan Sistem (Default)"</item>
+    <item msgid="8900559293912978337">"Mono"</item>
+    <item msgid="8883739882299884241">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Optimalkan untuk Kualitas Audio (990kbps/909kbps)"</item>
+    <item msgid="2921767058740704969">"Kualitas Audio dan Sambungan Seimbang (660kbps/606kbps)"</item>
+    <item msgid="3682554248829489641">"Optimalkan untuk Kualitas Sambungan (330kbps/303kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Optimalkan untuk Kualitas Audio"</item>
+    <item msgid="4327143584633311908">"Kualitas Audio dan Sambungan Seimbang"</item>
+    <item msgid="6155648878105378550">"Optimalkan untuk Kualitas Sambungan"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Nonaktif"</item>
     <item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index a2f13ae..12d61fe 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Data seluler selalu aktif"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Nonaktifkan volume absolut"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec Audio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Pilih Codec Audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Frekuensi Sampel Audio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Pilih Codec Audio Bluetooth:\nFrekuensi Sampel"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bit Per Sampel Audio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Pilih Codec Audio Bluetooth:\nBit Per Sampel"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Mode Channel Audio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Pilih Codec Audio Bluetooth:\nMode Channel"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Codec LDAC Audio Bluetooth: Kualitas Pemutaran"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Pilih Codec LDAC Audio Bluetooth:\nKualitas Pemutaran"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streaming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Tampilkan opsi untuk sertifikasi layar nirkabel"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Tingkatkan level pencatatan log Wi-Fi, tampilkan per SSID RSSI di Pemilih Wi‑Fi"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Jika diaktifkan, Wi-Fi akan menjadi lebih agresif dalam mengalihkan sambungan data ke Seluler saat sinyal Wi-Fi lemah"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Bantuan &amp; masukan"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Masukkan sandi untuk mengembalikan ke setelan pabrik dalam mode demo"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Berikutnya"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Perlu sandi"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-is/arrays.xml b/packages/SettingsLib/res/values-is/arrays.xml
index 94ce957..e3f2ba3 100644
--- a/packages/SettingsLib/res/values-is/arrays.xml
+++ b/packages/SettingsLib/res/values-is/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Nota val kerfisins (sjálfgefið)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Nota val kerfisins (sjálfgefið)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Nota val kerfisins (sjálfgefið)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48,0 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Nota val kerfisins (sjálfgefið)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48,0 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Nota val kerfisins (sjálfgefið)"</item>
+    <item msgid="5618929009984956469">"16 bitar/úrtak"</item>
+    <item msgid="3412640499234627248">"24 bitar/úrtak"</item>
+    <item msgid="121583001492929387">"32 bitar/úrtak"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Nota val kerfisins (sjálfgefið)"</item>
+    <item msgid="4726688794884191540">"16 bitar/úrtak"</item>
+    <item msgid="305344756485516870">"24 bitar/úrtak"</item>
+    <item msgid="244568657919675099">"32 bitar/úrtak"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Nota val kerfisins (sjálfgefið)"</item>
+    <item msgid="4106832974775067314">"Einóma"</item>
+    <item msgid="5571632958424639155">"Víðóma"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Nota val kerfisins (sjálfgefið)"</item>
+    <item msgid="8900559293912978337">"Einóma"</item>
+    <item msgid="8883739882299884241">"Víðóma"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Fínstilla fyrir hljóðgæði (990 kbps / 909 kbps)"</item>
+    <item msgid="2921767058740704969">"Jafnvægi á milli gæða hljóðs og tengingar (660 kbps / 606 kbps)"</item>
+    <item msgid="3682554248829489641">"Fínstilla fyrir gæði tengingar (330 kbps / 303 kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Fínstilla fyrir hljóðgæði"</item>
+    <item msgid="4327143584633311908">"Jafnvægi á milli gæða hljóðs og tengingar"</item>
+    <item msgid="6155648878105378550">"Fínstilla fyrir gæði tengingar"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Slökkt"</item>
     <item msgid="1593289376502312923">"64 k"</item>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index f50f97e..844a3b4 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Alltaf kveikt á farsímagögnum"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Slökkva á samstillingu hljóðstyrks"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth hljóðkóðari"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Velja Bluetooth-hljóðkóðara"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bluetooth hljóðtökutíðni"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Velja hljóðkóðara Bluetooth:\ntökutíðni"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bluetooth hljóðbitar í úrtaki"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Velja hljóðkóðara Bluetooth:\nbitar í úrtaki"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Hljóðrásarstilling Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Velja hljóðkóðara Bluetooth:\nstilling rásar"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth LDAC-hljóðkóðari: gæði spilunar"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Velja Bluetooth LDAC-hljóðkóðara:\ngæði spilunar"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streymi: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Sýna valkosti fyrir vottun þráðlausra skjáa"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Auka skráningarstig Wi-Fi, sýna RSSI fyrir hvert SSID í Wi-Fi vali"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Þegar þetta er virkt mun Wi-Fi ganga harðar fram í að færa gagnatenginguna yfir til símkerfisins þegar Wi-Fi merkið er lélegt"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Hjálp og ábendingar"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Valmynd"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Sláðu inn aðgangsorð til að framkvæma núllstillingu í sýnisútgáfu"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Áfram"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Aðgangsorðs krafist"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-it/arrays.xml b/packages/SettingsLib/res/values-it/arrays.xml
index d5ca891c..588b23c 100644
--- a/packages/SettingsLib/res/values-it/arrays.xml
+++ b/packages/SettingsLib/res/values-it/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Usa selezione di sistema (predefinita)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Usa selezione di sistema (predefinita)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Usa selezione di sistema (predefinita)"</item>
+    <item msgid="8895532488906185219">"44.1 kHz"</item>
+    <item msgid="2909915718994807056">"48.0 kHz"</item>
+    <item msgid="3347287377354164611">"88.2 kHz"</item>
+    <item msgid="1234212100239985373">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Usa selezione di sistema (predefinita)"</item>
+    <item msgid="4482862757811638365">"44.1 kHz"</item>
+    <item msgid="354495328188724404">"48.0 kHz"</item>
+    <item msgid="7329816882213695083">"88.2 kHz"</item>
+    <item msgid="6967397666254430476">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Usa selezione di sistema (predefinita)"</item>
+    <item msgid="5618929009984956469">"16 bit/campione"</item>
+    <item msgid="3412640499234627248">"24 bit/campione"</item>
+    <item msgid="121583001492929387">"32 bit/campione"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Usa selezione di sistema (predefinita)"</item>
+    <item msgid="4726688794884191540">"16 bit/campione"</item>
+    <item msgid="305344756485516870">"24 bit/campione"</item>
+    <item msgid="244568657919675099">"32 bit/campione"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Usa selezione di sistema (predefinita)"</item>
+    <item msgid="4106832974775067314">"Mono"</item>
+    <item msgid="5571632958424639155">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Usa selezione di sistema (predefinita)"</item>
+    <item msgid="8900559293912978337">"Mono"</item>
+    <item msgid="8883739882299884241">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Ottimizza per qualità audio (990 kbps/909 kbps)"</item>
+    <item msgid="2921767058740704969">"Audio bilanciato e qualità di connessione (660 kbps/606 kbps)"</item>
+    <item msgid="3682554248829489641">"Ottimizza per qualità di connessione (330 kbps/303 kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Ottimizza per qualità audio"</item>
+    <item msgid="4327143584633311908">"Audio bilanciato e qualità di connessione"</item>
+    <item msgid="6155648878105378550">"Ottimizza per qualità di connessione"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Off"</item>
     <item msgid="1593289376502312923">"64 kB"</item>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 14f41fa..7e3fd48 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Dati cellulare sempre attivi"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Disattiva volume assoluto"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec audio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Seleziona il codec audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Frequenza di campionamento audio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Seleziona il codec audio Bluetooth:\nFrequenza di campionamento"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bit per campione dell\'audio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Seleziona il codec audio Bluetooth:\nBit per campione"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Modalità canale audio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Seleziona il codec audio Bluetooth:\nModalità canale"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Codec LDAC audio Bluetooth: qualità di riproduzione"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Seleziona il codec LDAC audio Bluetooth:\nQualità di riproduzione"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streaming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra opzioni per la certificazione display wireless"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumenta il livello di registrazione Wi-Fi, mostrando il SSID RSSI nel selettore Wi-Fi"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Quando questa impostazione è attivata, il Wi-Fi sarà più aggressivo nel passare la connessione dati al cellulare, quando il segnale Wi-Fi è basso"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Guida e feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Inserisci la password per eseguire il ripristino dei dati di fabbrica in modalità demo"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Avanti"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Password obbligatoria"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml
index 94af5f1..976eb71 100644
--- a/packages/SettingsLib/res/values-iw/arrays.xml
+++ b/packages/SettingsLib/res/values-iw/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"‏השתמש בבדיקת HDCP עבור תוכן DRM בלבד"</item>
     <item msgid="45075631231212732">"‏תמיד השתמש בבדיקת HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"שימוש בבחירת המערכת (ברירת המחדל)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"השתמש בבחירת המערכת (ברירת המחדל)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"שימוש בבחירת המערכת (ברירת המחדל)"</item>
+    <item msgid="8895532488906185219">"44.1 קילו-הרץ"</item>
+    <item msgid="2909915718994807056">"48.0 קילו-הרץ"</item>
+    <item msgid="3347287377354164611">"88.2 קילו-הרץ"</item>
+    <item msgid="1234212100239985373">"96.0 קילו-הרץ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"השתמש בבחירת המערכת (ברירת המחדל)"</item>
+    <item msgid="4482862757811638365">"44.1 קילו-הרץ"</item>
+    <item msgid="354495328188724404">"48.0 קילו-הרץ"</item>
+    <item msgid="7329816882213695083">"88.2 קילו-הרץ"</item>
+    <item msgid="6967397666254430476">"96.0 קילו-הרץ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"שימוש בבחירת המערכת (ברירת המחדל)"</item>
+    <item msgid="5618929009984956469">"16 סיביות לדגימה"</item>
+    <item msgid="3412640499234627248">"24 סיביות לדגימה"</item>
+    <item msgid="121583001492929387">"32 סיביות לדגימה"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"השתמש בבחירת המערכת (ברירת המחדל)"</item>
+    <item msgid="4726688794884191540">"16 סיביות לדגימה"</item>
+    <item msgid="305344756485516870">"24 סיביות לדגימה"</item>
+    <item msgid="244568657919675099">"32 סיביות לדגימה"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"שימוש בבחירת המערכת (ברירת המחדל)"</item>
+    <item msgid="4106832974775067314">"מונו"</item>
+    <item msgid="5571632958424639155">"סטריאו"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"השתמש בבחירת המערכת (ברירת המחדל)"</item>
+    <item msgid="8900559293912978337">"מונו"</item>
+    <item msgid="8883739882299884241">"סטריאו"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"‏אופטימיזציה להשגת איכות אודיו מרבית (990kbps/909kbps)"</item>
+    <item msgid="2921767058740704969">"‏איזון בין איכות החיבור לאיכות אודיו (660kbps/606kbps)"</item>
+    <item msgid="3682554248829489641">"‏אופטימיזציה להשגת איכות חיבור מרבית (330kbps/303kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"בצע אופטימיזציה לאיכות האודיו"</item>
+    <item msgid="4327143584633311908">"אזן בין איכות החיבור לאיכות אודיו"</item>
+    <item msgid="6155648878105378550">"בצע אופטימיזציה להשגת איכות חיבור מרבית"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"כבוי"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 5b26091..3e1bfdb 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"נתונים סלולריים פעילים תמיד"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"השבת עוצמת קול מוחלטת"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"‏Codec אודיו ל-Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"‏בחירת ‏Codec אודיו ל-Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"‏קצב דגימה של אודיו ל-Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"‏בחירת Codec אודיו ל-Bluetooth‏:\nקצב דגימה"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"‏מספר סיביות לדגימה באודיו ל-Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"‏בחירת codec אודיו ל-Bluetooth:‏\nסיביות לדגימה"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"‏מצב של ערוץ אודיו ל-Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"‏בחירת codec אודיו ל-Bluetooth:‏\nמצב ערוץ"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"‏Codec אודיו LDAC ל-Bluetooth: איכות נגינה"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"‏בחירת Codec אודיו LDAC ל-Bluetooth:‏\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">"‏הצג אפשרויות עבור אישור של תצוגת WiFi"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"‏העלה את רמת הרישום של Wi‑Fi ביומן, הצג לכל SSID RSSI ב-Wi‑Fi Picker"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"‏כשתכונה זו מופעלת, Wi-Fi יתנהג בצורה אגרסיבית יותר בעת העברת חיבור הנתונים לרשת הסלולרית כשאות ה-Wi-Fi חלש."</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"עזרה ומשוב"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"תפריט"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"הזן סיסמה כדי לבצע איפוס להגדרות היצרן במצב הדגמה"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"הבא"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"דרושה סיסמה"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 72f4595..a7d607f 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -362,4 +362,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"ヘルプとフィードバック"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"メニュー"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"デモモードで初期状態にリセットするには、パスワードを入力してください"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"次へ"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"パスワード必須"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ka/arrays.xml b/packages/SettingsLib/res/values-ka/arrays.xml
index 60779fe..ad04e15 100644
--- a/packages/SettingsLib/res/values-ka/arrays.xml
+++ b/packages/SettingsLib/res/values-ka/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"HDCP შემოწმების გამოყენება მხოლოდ DRM კონტენტის შემთხვევაში"</item>
     <item msgid="45075631231212732">"ყოველთვის გამოიყენე HDCP შემოწმება"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item>
+    <item msgid="8895532488906185219">"44,1 კჰც"</item>
+    <item msgid="2909915718994807056">"48,0 კჰც"</item>
+    <item msgid="3347287377354164611">"88,2 კჰც"</item>
+    <item msgid="1234212100239985373">"96,0 კჰც"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item>
+    <item msgid="4482862757811638365">"44,1 კჰც"</item>
+    <item msgid="354495328188724404">"48,0 კჰც"</item>
+    <item msgid="7329816882213695083">"88,2 კჰც"</item>
+    <item msgid="6967397666254430476">"96,0 კჰც"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item>
+    <item msgid="5618929009984956469">"16 ბიტი/ნიმუში"</item>
+    <item msgid="3412640499234627248">"24 ბიტი/ნიმუში"</item>
+    <item msgid="121583001492929387">"32 ბიტი/ნიმუში"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item>
+    <item msgid="4726688794884191540">"16 ბიტი/ნიმუში"</item>
+    <item msgid="305344756485516870">"24 ბიტი/ნიმუში"</item>
+    <item msgid="244568657919675099">"32 ბიტი/ნიმუში"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item>
+    <item msgid="4106832974775067314">"მონო"</item>
+    <item msgid="5571632958424639155">"სტერეო"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"სისტემის არჩეულის გამოყენება (ნაგულისხმევი)"</item>
+    <item msgid="8900559293912978337">"მონო"</item>
+    <item msgid="8883739882299884241">"სტერეო"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"აუდიოს ხარისხის ოპტიმიზაცია (990/909 კბიტი/წმ)"</item>
+    <item msgid="2921767058740704969">"აუდიოსა და კავშირის დაბალანსებული ხარისხი (660/606 კბიტი/წმ)"</item>
+    <item msgid="3682554248829489641">"კავშირის ხარისხის ოპტიმიზაცია (330/303 კბიტი/წმ)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"აუდიოს ხარისხის ოპტიმიზაცია"</item>
+    <item msgid="4327143584633311908">"აუდიოსა და კავშირის დაბალანსებული ხარისხი"</item>
+    <item msgid="6155648878105378550">"კავშირის ხარისხის ოპტიმიზაცია"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"გამორთული"</item>
     <item msgid="1593289376502312923">"64 კბაიტი"</item>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 058562e..6838fbc 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"ფიჭური მონაცემები ყოველთვის აქტიურია"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ხმის აბსოლუტური სიძლიერის გათიშვა"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth აუდიოს კოდეკი"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"აირჩიეთ Bluetooth აუდიოს კოდეკი"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bluetooth აუდიოს დისკრეტიზაციის სიხშირე"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"აირჩიეთ Bluetooth აუდიოს კოდეკის\nდისკრეტიზაციის სიხშირე"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bluetooth აუდიოს ბიტების რაოდენობა ნიმუშზე"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"აირჩიეთ Bluetooth აუდიოს კოდეკის\nბიტების რაოდენობა ნიმუშზე"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Bluetooth აუდიოს არხის რეჟიმი"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"აირჩიეთ Bluetooth აუდიოს კოდეკის\nარხის რეჟიმი"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth აუდიოს LDAC კოდეკის დაკვრის ხარისხი"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"აირჩიეთ Bluetooth აუდიოს 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_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi-ს აღრიცხვის დონის გაზრდა, Wi‑Fi ამომრჩეველში ყოველ SSID RSSI-ზე ჩვენება"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"თუ ჩართულია, Wi‑Fi სიგნალის შესუსტების შემთხვევაში Wi-Fi უფრო აქტიურად შეეცდება გადაიყვანოს ინტერნეტ-კავშირი მობილურ ინტერნეტზე"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"დახმარება და გამოხმაურება"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"მენიუ"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"შეიყვანეთ პაროლი დემო-რეჟიმში ქარხნულ მდგომარეობაზე დასაბრუნებლად"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"შემდეგი"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"საჭიროა პაროლი"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-kk/arrays.xml b/packages/SettingsLib/res/values-kk/arrays.xml
index f743606..056f17b 100644
--- a/packages/SettingsLib/res/values-kk/arrays.xml
+++ b/packages/SettingsLib/res/values-kk/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"HDCP (кең жолақты сандық мазмұн қорғау) тексеруді DRM (авторлық құқықты техникалық қорғау) мазмұны үшін ғана қолданыңыз"</item>
     <item msgid="45075631231212732">"Әрқашан HDCP (жоғары кең жолақты сандық мазмұн қорғаушы) тексерулерін қолданыңыз"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Жүйені таңдау (әдепкі)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Жүйені таңдау (әдепкі)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Жүйені таңдау (әдепкі)"</item>
+    <item msgid="8895532488906185219">"44,1 кГц"</item>
+    <item msgid="2909915718994807056">"48,0 кГц"</item>
+    <item msgid="3347287377354164611">"88,2 кГц"</item>
+    <item msgid="1234212100239985373">"96,0 кГц"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Жүйені таңдау (әдепкі)"</item>
+    <item msgid="4482862757811638365">"44,1 кГц"</item>
+    <item msgid="354495328188724404">"48,0 кГц"</item>
+    <item msgid="7329816882213695083">"88,2 кГц"</item>
+    <item msgid="6967397666254430476">"96,0 кГц"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Жүйені таңдау (әдепкі)"</item>
+    <item msgid="5618929009984956469">"16 бит/үлгі"</item>
+    <item msgid="3412640499234627248">"24 бит/үлгі"</item>
+    <item msgid="121583001492929387">"32 бит/үлгі"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Жүйені таңдау (әдепкі)"</item>
+    <item msgid="4726688794884191540">"16 бит/үлгі"</item>
+    <item msgid="305344756485516870">"24 бит/үлгі"</item>
+    <item msgid="244568657919675099">"32 бит/үлгі"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Жүйені таңдау (әдепкі)"</item>
+    <item msgid="4106832974775067314">"Моно"</item>
+    <item msgid="5571632958424639155">"Стерео"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Жүйені таңдау (әдепкі)"</item>
+    <item msgid="8900559293912978337">"Моно"</item>
+    <item msgid="8883739882299884241">"Стерео"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Аудиомазмұн сапасы бойынша оңтайландыру (990 кб/сек не 909 кб/сек)"</item>
+    <item msgid="2921767058740704969">"Теңгерілген аудиомазмұн мен байланыс сапасы (660 кб/сек не 606 кб/сек)"</item>
+    <item msgid="3682554248829489641">"Байланыс сапасы бойынша оңтайландыру (330 кб/сек не 303 кб/сек)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Аудиомазмұн сапасы бойынша оңтайландыру"</item>
+    <item msgid="4327143584633311908">"Теңгерілген аудиомазмұн мен байланыс сапасы"</item>
+    <item msgid="6155648878105378550">"Байланыс сапасы бойынша оңтайландыру"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Өшірулі"</item>
     <item msgid="1593289376502312923">"64 КБ"</item>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 69610fa..9372dbd 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Ұялы деректер әрқашан белсенді"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Абсолютті дыбыс деңгейін өшіру"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth аудимазмұн кодегі"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Bluetooth аудиокодегін таңдау"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bluetooth аудиомазмұны бойынша үлгі жиілігі"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Bluetooth аудиокодегін таңдау:\nдискреттеу жылдамдығы"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bluetooth аудиомазмұны бойынша әр үлгіге келетін биттер саны"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Bluetooth аудиокодегін таңдау:\nбит/үлгі"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Bluetooth аудиомазмұны бойынша арна режимі"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Bluetooth аудиокодегін таңдау:\nарна режимі"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth LDAC аудиокодегі: ойнату сапасы"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Bluetooth 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_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi жур. тір. дең. арт., Wi‑Fi желісін таңдағышта әр SSID RSSI бойынша көрсету"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Wi‑Fi сигналы әлсіз болғанда, деректер байланысы мәжбүрлі түрде ұялы желіге ауысады"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Анықтама және пікір"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Mәзір"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Демо режимде зауыттық мәндерге қайтару үшін құпия сөзді енгізу"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Келесі"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Құпия сөз қажет"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 205f01b..0b1ba5e 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"ជំនួយ និងមតិស្ថាបនា"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"ម៉ឺនុយ"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"បញ្ចូល​ពាក្យ​សម្ងាត់ ដើម្បី​កំណត់​​ដូចចេញ​ពី​រោងចក្រឡើង​វិញ​នៅក្នុង​មុខងារ​សាកល្បង"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"បន្ទាប់"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"តម្រូវ​ឲ្យ​មានពាក្យ​សម្ងាត់"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml
index d26f95a..2cfe328 100644
--- a/packages/SettingsLib/res/values-kn/arrays.xml
+++ b/packages/SettingsLib/res/values-kn/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"DRM ವಿಷಯಗಳಿಗೆ ಮಾತ್ರ HDCP ಪರೀಕ್ಷಿಸುವಿಕೆಯನ್ನು ಬಳಸು"</item>
     <item msgid="45075631231212732">"HDCP ಪರಿಶೀಲನೆಯನ್ನು ಯಾವಾಗಲೂ ಬಳಸು"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
+    <item msgid="8895532488906185219">"44.1 kHz"</item>
+    <item msgid="2909915718994807056">"48.0 kHz"</item>
+    <item msgid="3347287377354164611">"88.2 kHz"</item>
+    <item msgid="1234212100239985373">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
+    <item msgid="4482862757811638365">"44.1 kHz"</item>
+    <item msgid="354495328188724404">"48.0 kHz"</item>
+    <item msgid="7329816882213695083">"88.2 kHz"</item>
+    <item msgid="6967397666254430476">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
+    <item msgid="5618929009984956469">"16 ಬಿಟ್ಸ್/ಮಾದರಿ"</item>
+    <item msgid="3412640499234627248">"24 ಬಿಟ್ಸ್/ಮಾದರಿ"</item>
+    <item msgid="121583001492929387">"32 ಬಿಟ್ಸ್/ಮಾದರಿ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
+    <item msgid="4726688794884191540">"16 ಬಿಟ್ಸ್/ಮಾದರಿ"</item>
+    <item msgid="305344756485516870">"24 ಬಿಟ್ಸ್/ಮಾದರಿ"</item>
+    <item msgid="244568657919675099">"32 ಬಿಟ್ಸ್/ಮಾದರಿ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
+    <item msgid="4106832974775067314">"ಮೊನೊ"</item>
+    <item msgid="5571632958424639155">"ಸ್ಟೀರಿಯೊ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"ಸಿಸ್ಟಂ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿ (ಡಿಫಾಲ್ಟ್)"</item>
+    <item msgid="8900559293912978337">"ಮೊನೊ"</item>
+    <item msgid="8883739882299884241">"ಸ್ಟೀರಿಯೊ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"ಆಡಿಯೊ ಗುಣಮಟ್ಟಕ್ಕಾಗಿ (990kbps/909kbps) ಆಪ್ಟಿಮೈಸ್ ಮಾಡಿ"</item>
+    <item msgid="2921767058740704969">"ಸಂತುಲಿತ ಆಡಿಯೊ ಮತ್ತು ಸಂಪರ್ಕದ ಗುಣಮಟ್ಟ (660kbps/606kbps)"</item>
+    <item msgid="3682554248829489641">"ಸಂಪರ್ಕದ ಗುಣಮಟ್ಟಕ್ಕಾಗಿ (330kbps/303kbps) ಆಪ್ಟಿಮೈಸ್ ಮಾಡಿ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"ಆಡಿಯೊ ಗುಣಮಟ್ಟಕ್ಕಾಗಿ ಆಪ್ಟಿಮೈಸ್ ಮಾಡಿ"</item>
+    <item msgid="4327143584633311908">"ಸಂತುಲಿತ ಆಡಿಯೊ ಮತ್ತು ಸಂಪರ್ಕದ ಗುಣಮಟ್ಟ"</item>
+    <item msgid="6155648878105378550">"ಸಂಪರ್ಕದ ಗುಣಮಟ್ಟಕ್ಕಾಗಿ ಆಪ್ಟಿಮೈಸ್ ಮಾಡಿ"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"ಆಫ್"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index e43883e..99577f7 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"ಸೆಲ್ಯುಲರ್ ಡೇಟಾ ಯಾವಾಗಲೂ ಸಕ್ರಿಯ"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ಸಂಪೂರ್ಣ ವಾಲ್ಯೂಮ್‌ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೋ ಕೋಡೆಕ್"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Bluetooth ಆಡಿಯೊ ಕೋಡೆಕ್ ಆಯ್ಕೆ ಮಾಡಿ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೋ ಮಾದರಿ ದರ"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Bluetooth ಆಡಿಯೋ ಕೋಡೆಕ್:\nಮಾದರಿ ದರ ಆಯ್ಕೆ ಮಾಡಿ"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"ಬ್ಲೂಟೂತ್‌ ಆಡಿಯೊ ಬಿಟ್ಸ್‌‌ನ ಪ್ರತಿ ಮಾದರಿ"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Bluetooth ಆಡಿಯೋ ಕೋಡೆಕ್‌:\nಬಿಟ್ಸ್ ಪ್ರತಿ ಮಾದರಿ ಆಯ್ಕೆ ಮಾಡಿ"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೋ ಚಾನೆಲ್ ಮೋಡ್"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Bluetooth ಆಡಿಯೋ ಕೋಡೆಕ್:\nಚಾನೆಲ್ ಮೋಡ್ ಆಯ್ಕೆ ಮಾಡಿ"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth ಆಡಿಯೊ LDAC ಕೋಡೆಕ್: ಪ್ಲೇಬ್ಯಾಕ್ ಗುಣಮಟ್ಟ"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Bluetooth ಆಡಿಯೊ 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_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ಲಾಗಿಂಗ್ ಮಟ್ಟನ್ನು ಹೆಚ್ಚಿಸಿ, Wi‑Fi ಆಯ್ಕೆಯಲ್ಲಿ ಪ್ರತಿಯೊಂದು SSID RSSI ತೋರಿಸಿ"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"ಸಕ್ರಿಯಗೊಂಡರೆ, Wi‑Fi ಸಿಗ್ನಲ್ ದುರ್ಬಲವಾಗಿದ್ದರೂ ಕೂಡ, ಸೆಲ್ಯುಲರ್‌ಗೆ ಡೇಟಾ ಸಂಪರ್ಕವನ್ನು ಹಸ್ತಾಂತರಿಸುವಲ್ಲಿ Wi‑Fi ಹೆಚ್ಚು ಆಕ್ರಮಣಕಾರಿಯಾಗಿರುತ್ತದೆ"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"ಸಹಾಯ ಮತ್ತು ಪ್ರತಿಕ್ರಿಯೆ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"ಮೆನು"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"ಫ್ಯಾಕ್ಟರಿ ರಿಸೆಟ್‌ಗೆ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"ಮುಂದೆ"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"ಪಾಸ್‌ವರ್ಡ್ ಅಗತ್ಯವಿದೆ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 0a8c727..3606497 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"고객센터"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"메뉴"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"데모 모드에서 초기화하려면 비밀번호 입력"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"다음"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"비밀번호 입력 필요"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml
index 724d0c7..4cdee97 100644
--- a/packages/SettingsLib/res/values-ky/arrays.xml
+++ b/packages/SettingsLib/res/values-ky/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"HDCP текшерүү DRM мазмунуна гана колдонулсун"</item>
     <item msgid="45075631231212732">"Ар дайым HDCP текшерүү колдонулсун"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Тутум тандаганды колдонуу (демейки)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Тутум тандаганды колдонуу (демейки)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Тутум тандаганды колдонуу (демейки)"</item>
+    <item msgid="8895532488906185219">"44,1 кГц"</item>
+    <item msgid="2909915718994807056">"48,0 кГц"</item>
+    <item msgid="3347287377354164611">"88,2 кГц"</item>
+    <item msgid="1234212100239985373">"96,0 кГц"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Тутум тандаганды колдонуу (демейки)"</item>
+    <item msgid="4482862757811638365">"44,1 кГц"</item>
+    <item msgid="354495328188724404">"48,0 кГц"</item>
+    <item msgid="7329816882213695083">"88,2 кГц"</item>
+    <item msgid="6967397666254430476">"96,0 кГц"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Тутум тандаганды колдонуу (демейки)"</item>
+    <item msgid="5618929009984956469">"16 бит/үлгү"</item>
+    <item msgid="3412640499234627248">"24 бит/үлгү"</item>
+    <item msgid="121583001492929387">"32 бит/үлгү"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Тутум тандаганды колдонуу (демейки)"</item>
+    <item msgid="4726688794884191540">"16 бит/үлгү"</item>
+    <item msgid="305344756485516870">"24 бит/үлгү"</item>
+    <item msgid="244568657919675099">"32 бит/үлгү"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Тутум тандаганды колдонуу (демейки)"</item>
+    <item msgid="4106832974775067314">"Моно"</item>
+    <item msgid="5571632958424639155">"Стерео"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Тутум тандаганды колдонуу (демейки)"</item>
+    <item msgid="8900559293912978337">"Моно"</item>
+    <item msgid="8883739882299884241">"Стерео"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Аудио сапаты үчүн оптималдаштыруу (990кб/сек./909кб/сек.)"</item>
+    <item msgid="2921767058740704969">"Теңделген аудио жана туташуу сапаты (660кб/сек./606кб/сек.)"</item>
+    <item msgid="3682554248829489641">"Туташуу сапаты үчүн оптималдаштыруу (330кб/сек./303кб/сек.)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Аудио сапаты үчүн оптималдаштыруу"</item>
+    <item msgid="4327143584633311908">"Теңделген аудио жана туташуу сапаты"</item>
+    <item msgid="6155648878105378550">"Туташуу сапаты үчүн оптималдаштыруу"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Өчүк"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 1a8aee3..6608ae5 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Уюлдук дайындар ар дайым активдүү"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Үндүн абсолюттук деңгээли өчүрүлсүн"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth аудио кодек"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Bluetooth аудио кодегин тандаңыз"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bluetooth аудио үлгүсүнүн ылдамдыгы"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Bluetooth аудио кодегин тандаңыз:\nҮлгү жыштыгы"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Бир үлгүдөгү Bluetooth аудио биттери"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Bluetooth аудио кодегин тандаңыз:\nБир үлгүдөгү биттер"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Bluetooth аудио каналынын режими"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Bluetooth аудио кодегин тандаңыз:\nКанал режими"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth аудио LDAC кодеги: Ойнотуу сапаты"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Bluetooth аудио 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_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi Кармагычта Wi‑Fi протокол деңгээлин жогорулатуу жана ар бир SSID RSSI үчүн көрсөтүү."</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Иштетилгенде, Wi-Fi байланышы үзүл-кесил болуп жатканда, Wi-Fi дайындарды уюктук операторго өжөрлүк менен өткөрөт."</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Жардам жана жооп пикир"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Меню"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Демо режиминде демейки жөндөөлөргө кайтаруу үчүн сырсөздү киргизиңиз"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Кийинки"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Сырсөз талап кылынат"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lo/arrays.xml b/packages/SettingsLib/res/values-lo/arrays.xml
index 4b14eeb..0967128 100644
--- a/packages/SettingsLib/res/values-lo/arrays.xml
+++ b/packages/SettingsLib/res/values-lo/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"ໃຊ້ການກວດສອບ HDCP ສຳລັບເນື້ອຫາ DRM ເທົ່ານັ້ນ"</item>
     <item msgid="45075631231212732">"ໃຊ້ການກວດສອບ HDCP ສະເໝີ"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Use System Selection (Default)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX-HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Use System Selection (Default)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX-HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Use System Selection (Default)"</item>
+    <item msgid="8895532488906185219">"44.1 kHz"</item>
+    <item msgid="2909915718994807056">"48.0 kHz"</item>
+    <item msgid="3347287377354164611">"88.2 kHz"</item>
+    <item msgid="1234212100239985373">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Use System Selection (Default)"</item>
+    <item msgid="4482862757811638365">"44.1 kHz"</item>
+    <item msgid="354495328188724404">"48.0 kHz"</item>
+    <item msgid="7329816882213695083">"88.2 kHz"</item>
+    <item msgid="6967397666254430476">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Use System Selection (Default)"</item>
+    <item msgid="5618929009984956469">"16 bits/sample"</item>
+    <item msgid="3412640499234627248">"24 bits/sample"</item>
+    <item msgid="121583001492929387">"32 bits/sample"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Use System Selection (Default)"</item>
+    <item msgid="4726688794884191540">"16 bits/sample"</item>
+    <item msgid="305344756485516870">"24 bits/sample"</item>
+    <item msgid="244568657919675099">"32 bits/sample"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Use System Selection (Default)"</item>
+    <item msgid="4106832974775067314">"ໂທນດຽວ"</item>
+    <item msgid="5571632958424639155">"ສະເຕຣິໂອ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Use System Selection (Default)"</item>
+    <item msgid="8900559293912978337">"ໂທນດຽວ"</item>
+    <item msgid="8883739882299884241">"ສະເຕຣິໂອ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Optimize for Audio Quality (990kbps/909kbps)"</item>
+    <item msgid="2921767058740704969">"Balanced Audio And Connection Quality (660kbps/606kbps)"</item>
+    <item msgid="3682554248829489641">"Optimize for Connection Quality (330kbps/303kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Optimize for Audio Quality"</item>
+    <item msgid="4327143584633311908">"Balanced Audio And Connection Quality"</item>
+    <item msgid="6155648878105378550">"Optimize for Connection Quality"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"ປິດ"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 569c0ce..9c493f2 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"ຂໍ້​ມູນ​ມື​ຖື​ເປີດ​ຢູ່​ສະ​ເໝີ"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ປິດໃຊ້ລະດັບສຽງສົມບູນ"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio Codec"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Select Bluetooth Audio Codec"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bluetooth Audio Sample Rate"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Select Bluetooth Audio Codec:\nSample Rate"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bluetooth Audio Bits Per Sample"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Select Bluetooth Audio Codec:\nBits Per Sample"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Bluetooth Audio Channel Mode"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Select Bluetooth Audio Codec:\nChannel Mode"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth Audio LDAC Codec: Playback Quality"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Select Bluetooth Audio LDAC Codec:\nPlayback Quality"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streaming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ສະແດງໂຕເລືອກສຳລັບການສະແດງການຮັບຮອງລະບົບໄຮ້ສາຍ"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ເພີ່ມ​ລະ​ດັບ​ການ​ເກັບ​ປະ​ຫວັດ Wi‑Fi, ສະ​ແດງ​ຕໍ່ SSID RSSI ​ໃນ​ Wi‑Fi Picker"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"ເມື່ອ​ເປີດ​ນຳ​ໃຊ້​ແລ້ວ, ເຄືອ​ຂ່າຍ Wi-Fi ຈະ​ຖືກ​ປ່ຽນ​ໄປ​ໃຊ້​ເຄືອ​ຂ່າຍ​ໂທ​ລະ​ສັບ​ແທນ​ຫາກ​ສັນ​ຍານ Wi-Fi ອ່ອນ"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"ຊ່ວຍເຫຼືອ &amp; ຄຳຕິຊົມ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"ເມນູ"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Enter password to perform factory reset in demo mode"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"ຕໍ່ໄປ"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"​ຕ້ອງ​ໃສ່​ລະ​ຫັດ​ຜ່ານ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lt/arrays.xml b/packages/SettingsLib/res/values-lt/arrays.xml
index deed74f..29a4671 100644
--- a/packages/SettingsLib/res/values-lt/arrays.xml
+++ b/packages/SettingsLib/res/values-lt/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Naudoti sistemos pasirink. (numatytasis)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Naudoti sistemos pasirink. (numatytasis)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Naudoti sistemos pasirink. (numatytasis)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48,0 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Naudoti sistemos pasirink. (numatytasis)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48,0 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Naudoti sistemos pasirink. (numatytasis)"</item>
+    <item msgid="5618929009984956469">"16 bitų pavyzdyje"</item>
+    <item msgid="3412640499234627248">"24 bitai pavyzdyje"</item>
+    <item msgid="121583001492929387">"32 bitai pavyzdyje"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Naudoti sistemos pasirink. (numatytasis)"</item>
+    <item msgid="4726688794884191540">"16 bitų pavyzdyje"</item>
+    <item msgid="305344756485516870">"24 bitai pavyzdyje"</item>
+    <item msgid="244568657919675099">"32 bitai pavyzdyje"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Naudoti sistemos pasirink. (numatytasis)"</item>
+    <item msgid="4106832974775067314">"Monofoninis garsas"</item>
+    <item msgid="5571632958424639155">"Stereofoninis garsas"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Naudoti sistemos pasirink. (numatytasis)"</item>
+    <item msgid="8900559293912978337">"Monofoninis garsas"</item>
+    <item msgid="8883739882299884241">"Stereofoninis garsas"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Optimizuoti garso kokybę (990 kbps / 909 kbps)"</item>
+    <item msgid="2921767058740704969">"Subalansuotą garso ir ryšio kokybė (660 kbps / 606 kbps)"</item>
+    <item msgid="3682554248829489641">"Optimizuoti ryšio kokybę (330 kbps / 303 kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Optimizuoti garso kokybę"</item>
+    <item msgid="4327143584633311908">"Subalansuota garso ir ryšio kokybė"</item>
+    <item msgid="6155648878105378550">"Optimizuoti ryšio kokybę"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Išjungta"</item>
     <item msgid="1593289376502312923">"64 KB"</item>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 28329cc..3090d30 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Korinio ryšio duomenys visada aktyvūs"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Išjungti didžiausią garsą"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"„Bluetooth“ garso kodekas"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Pasirinkite „Bluetooth“ garso kodeką"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"„Bluetooth“ garso pavyzdžio dažnis"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Pasirinkite „Bluetooth“ garso kodekas:\nimties dydis"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"„Bluetooth“ garso įrašo bitų skaičius pavyzdyje"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Pasirinkite „Bluetooth“ garso kodeką:\nbitų skaičius viename pavyzdyje"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"„Bluetooth“ garso kanalo režimas"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Pasirinkite „Bluetooth“ garso kodeką:\n kanalo režimas"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"„Bluetooth“ garso LDAC kodekas: atkūrimo kokybė"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Pasirinkite „Bluetooth“ garso LDAC kodeką:\natkūrimo kokybė"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Srautinis perdavimas: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Rodyti belaidžio rodymo sertifikavimo parinktis"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Padidinti „Wi‑Fi“ įrašymo į žurnalą lygį, rodyti SSID RSSI „Wi-Fi“ rinkiklyje"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Jei įgalinta ši parinktis, „Wi‑Fi“ agresyviau perduos duomenų ryšį į mobiliojo ryšio tinklą, kai „Wi‑Fi“ signalas bus silpnas"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Pagalba ir atsiliepimai"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meniu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Įv. slapt. ir atk. gam. nust. dem. rež."</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Kitas"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Būtina nurodyti slaptažodį"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index b64216a..070583e 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Palīdzība un atsauksmes"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Izvēlne"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Iev. paroli, lai atiest. rūpnīcas iest. dem. režīmā"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Tālāk"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Nepieciešama parole"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mk/arrays.xml b/packages/SettingsLib/res/values-mk/arrays.xml
index 72124f7..e27d02d 100644
--- a/packages/SettingsLib/res/values-mk/arrays.xml
+++ b/packages/SettingsLib/res/values-mk/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"Користи ХДЦП проверка само за ДРМ содржина"</item>
     <item msgid="45075631231212732">"Секогаш користи ХДЦП проверка"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Користи избор на системот (стандардно)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Користи избор на системот (стандардно)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Користи избор на системот (стандардно)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48,0 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Користи избор на системот (стандардно)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48,0 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Користи избор на системот (стандардно)"</item>
+    <item msgid="5618929009984956469">"16 бита/семпл"</item>
+    <item msgid="3412640499234627248">"24 бита/семпл"</item>
+    <item msgid="121583001492929387">"32 бита/семпл"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Користи избор на системот (стандардно)"</item>
+    <item msgid="4726688794884191540">"16 бита/семпл"</item>
+    <item msgid="305344756485516870">"24 бита/семпл"</item>
+    <item msgid="244568657919675099">"32 бита/семпл"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Користи избор на системот (стандардно)"</item>
+    <item msgid="4106832974775067314">"Моно"</item>
+    <item msgid="5571632958424639155">"Стерео"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Користи избор на системот (стандардно)"</item>
+    <item msgid="8900559293912978337">"Моно"</item>
+    <item msgid="8883739882299884241">"Стерео"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Оптимизирај за квалитет на аудиото (990 kb/s/909 kb/s)"</item>
+    <item msgid="2921767058740704969">"Балансиран квалитет на звукот и врската (660 kb/s/606 kb/s)"</item>
+    <item msgid="3682554248829489641">"Оптимизирај за квалитет на врската (330 kb/s/303 kb/s)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Оптимизирај за квалитет на аудиото"</item>
+    <item msgid="4327143584633311908">"Балансиран квалитет на звукот и врската"</item>
+    <item msgid="6155648878105378550">"Оптимизирај за квалитет на врската"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Исклучено"</item>
     <item msgid="1593289376502312923">"64.000"</item>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index df106ed..0662c8f 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Мобилниот интернет е секогаш активен"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Оневозможете апсолутна јачина на звук"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Кодек за аудио преку Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Изберете кодек за аудио преку Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Стапка на семпл преку Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Изберете кодек за аудио преку Bluetooth:\nСтапка на примерок"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Аудио бит-по-семпл преку Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Изберете кодек за аудио преку Bluetooth:\nБитови/примерок"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Режим на канал за аудио преку Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Изберете кодек за аудио преку Bluetooth:\nРежим на канал"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Кодек за LDAC-аудио преку Bluetooth: квалитет на репродукција"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Изберете кодек за LDAC-аудио преку Bluetooth:\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_verbose_logging_summary" msgid="6615071616111731958">"Зголеми Wi‑Fi ниво на пријавување, прикажи по SSID RSSI во Wi‑Fi бирач"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Кога е вклучено, Wi-Fi ќе биде поагресивно при предавање на поврзувањето со податоци на мобилната мрежа при слаб сигнал на Wi-Fi."</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Помош и повратни информации"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Мени"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Внесете лозинка за фаб. ресет. во демо"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Следно"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Потребна е лозинка"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml
index 38ba63a..eb7ef5f 100644
--- a/packages/SettingsLib/res/values-ml/arrays.xml
+++ b/packages/SettingsLib/res/values-ml/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"DRM ഉള്ളടക്കത്തിനുമാത്രമായി HDCP പരിശോധന ഉപയോഗിക്കുക"</item>
     <item msgid="45075631231212732">"എല്ലായ്‌പ്പോഴും HDCP പരിശോധന ഉപയോഗിക്കുക"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ ‌(ഡിഫോൾട്ട്)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ ‌(ഡിഫോൾട്ട്)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ ‌(ഡിഫോൾട്ട്)"</item>
+    <item msgid="8895532488906185219">"44.1 kHz"</item>
+    <item msgid="2909915718994807056">"48.0 kHz"</item>
+    <item msgid="3347287377354164611">"88.2 kHz"</item>
+    <item msgid="1234212100239985373">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ ‌(ഡിഫോൾട്ട്)"</item>
+    <item msgid="4482862757811638365">"44.1 kHz"</item>
+    <item msgid="354495328188724404">"48.0 kHz"</item>
+    <item msgid="7329816882213695083">"88.2 kHz"</item>
+    <item msgid="6967397666254430476">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ ‌(ഡിഫോൾട്ട്)"</item>
+    <item msgid="5618929009984956469">"16 ബിറ്റ്/സാമ്പിൾ"</item>
+    <item msgid="3412640499234627248">"24 ബിറ്റ്/സാമ്പിൾ"</item>
+    <item msgid="121583001492929387">"32 ബിറ്റ്/സാമ്പിൾ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ ‌(ഡിഫോൾട്ട്)"</item>
+    <item msgid="4726688794884191540">"16 ബിറ്റ്/സാമ്പിൾ"</item>
+    <item msgid="305344756485516870">"16 ബിറ്റ്/സാമ്പിൾ"</item>
+    <item msgid="244568657919675099">"32 ബിറ്റ്/സാമ്പിൾ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ ‌(ഡിഫോൾട്ട്)"</item>
+    <item msgid="4106832974775067314">"മോണോ"</item>
+    <item msgid="5571632958424639155">"സ്റ്റീരിയോ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"സിസ്റ്റം സെലക്ഷൻ ഉപയോഗിക്കൂ ‌(ഡിഫോൾട്ട്)"</item>
+    <item msgid="8900559293912978337">"മോണോ"</item>
+    <item msgid="8883739882299884241">"സ്റ്റീരിയോ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"ഓഡിയോ നിലവാരമുയർത്താൻ ഒപ്റ്റിമൈസ് ചെയ്യുക (990kbps/909kbps)"</item>
+    <item msgid="2921767058740704969">"സന്തുലിതമായ ‌ഓഡിയോ/കണക്ഷൻ നിലവാരം (660kbps/606kbps)"</item>
+    <item msgid="3682554248829489641">"കണക്ഷൻ നിലവാരമുയർത്താൻ ഒപ്റ്റിമൈസ് ചെയ്യുക (330kbps/303kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"ശബ്ദനിലവാരമുയർത്താൻ ഒപ്റ്റിമൈസ് ചെയ്യുക"</item>
+    <item msgid="4327143584633311908">"സന്തുലിതമായ ‌ഓഡിയോ/കണക്ഷൻ നിലവാരം"</item>
+    <item msgid="6155648878105378550">"കണക്ഷൻ നിലവാരമുയർത്താൻ ഒപ്റ്റിമൈസ് ചെയ്യുക"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"ഓഫ്"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index f61b71d..b238625 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"സെല്ലുലാർ ഡാറ്റ എല്ലായ്‌പ്പോഴും സജീവം"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"അബ്‌സൊല്യൂട്ട് വോളിയം പ്രവർത്തനരഹിതമാക്കുക"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth ഓഡിയോ കോഡെക്"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Bluetooth ഓഡിയോ കോഡെക് തിരഞ്ഞെടുക്കുക"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bluetooth ഓഡിയോ സാമ്പിൾ നിരക്ക്"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Bluetooth ഓഡിയോ കോഡെക് തിരഞ്ഞെടുക്കുക:\nസാമ്പിൾ നിരക്ക്"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"പ്രതി സാമ്പിളിലെ Bluetooth ഓഡിയോ ബിറ്റ് നി"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Bluetooth ഓഡിയോ കോഡെക് തിരഞ്ഞെടുക്കുക:\nബിറ്റ്‌/സാമ്പിൾ"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Bluetooth ഓഡിയോ ചാനൽ മോഡ്"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Bluetooth ഓഡിയോ കോഡെക് തിരഞ്ഞെടുക്കുക:\nചാനൽ മോഡ്"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth ഓഡിയോ LDAC കോഡെക്: പ്ലേബാക്ക് ‌നിലവാരം"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Bluetooth ഓഡിയോ 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_verbose_logging_summary" msgid="6615071616111731958">"വൈഫൈ പിക്കറിൽ ഓരോ SSID RSSI പ്രകാരം കാണിക്കാൻ വൈഫൈ ലോഗിംഗ് നില വർദ്ധിപ്പിക്കുക"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"പ്രവർത്തനക്ഷമമായിരിക്കുമ്പോൾ, വൈഫൈ സിഗ്‌നൽ കുറവായിരിക്കുന്ന സമയത്ത് സെല്ലുലാറിലേക്ക് ഡാറ്റ കണക്ഷൻ മുഖേന കൈമാറുന്നതിൽ വൈഫൈ കൂടുതൽ പ്രവർത്തനക്ഷമമാകും"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"സഹായവും പ്രതികരണവും"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"മെനു"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"ഡെമോ ‌മോഡിൽ ഫാക്ടറി റീസെറ്റിന് പാസ്‌വേഡ് നൽകുക"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"അടുത്തത്"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"പാസ്‌വേഡ് ആവശ്യമാണ്"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mn/arrays.xml b/packages/SettingsLib/res/values-mn/arrays.xml
index f4d1ca3..8902946 100644
--- a/packages/SettingsLib/res/values-mn/arrays.xml
+++ b/packages/SettingsLib/res/values-mn/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"HDCP шалгахыг зөвхөн DRM контентэд ашиглах"</item>
     <item msgid="45075631231212732">"Байнга HDCP шалгахыг ашиглах"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item>
+    <item msgid="8895532488906185219">"44.1 кГц"</item>
+    <item msgid="2909915718994807056">"48.0 кГц"</item>
+    <item msgid="3347287377354164611">"88.2 кГц"</item>
+    <item msgid="1234212100239985373">"96.0 кГц"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item>
+    <item msgid="4482862757811638365">"44.1 кГц"</item>
+    <item msgid="354495328188724404">"48.0 кГц"</item>
+    <item msgid="7329816882213695083">"88.2 кГц"</item>
+    <item msgid="6967397666254430476">"96.0 кГц"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item>
+    <item msgid="5618929009984956469">"16 бит/жишээ"</item>
+    <item msgid="3412640499234627248">"24 бит/жишээ"</item>
+    <item msgid="121583001492929387">"32 бит/жишээ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item>
+    <item msgid="4726688794884191540">"16 бит/жишээ"</item>
+    <item msgid="305344756485516870">"24 бит/жишээ"</item>
+    <item msgid="244568657919675099">"32 бит/жишээ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item>
+    <item msgid="4106832974775067314">"Моно"</item>
+    <item msgid="5571632958424639155">"Стерео"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Системийн сонголтыг ашиглах (Өгөгдмөл)"</item>
+    <item msgid="8900559293912978337">"Моно"</item>
+    <item msgid="8883739882299884241">"Стерео"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Аудио чанарт оновчлох (990кб/цаг/909кб/цаг)"</item>
+    <item msgid="2921767058740704969">"Аудио, холболтын чанарыг тэнцүүлсэн (660кб/цаг/606кб/цаг)"</item>
+    <item msgid="3682554248829489641">"Холболтын чанарт оновчлох (330кб/цаг/303кб/цаг)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Аудио чанарт оновчлох"</item>
+    <item msgid="4327143584633311908">"Аудио, холболтын чанарыг тэнцүүлсэн"</item>
+    <item msgid="6155648878105378550">"Холболтын чанарт оновчлох"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Идэвхгүй"</item>
     <item msgid="1593289376502312923">"64000"</item>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 940e0b0..68f3df5 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Үүрэн холбооны датаг үргэлж идэвхтэй байлгана"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Үнэмлэхүй дууны түвшинг идэвхгүй болгох"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth аудио кодлогч"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Bluetooth аудио кодлогч сонгох"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bluetooth аудио жишээний үнэлгээ"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Bluetooth аудио кодлогч сонгох:\nЖишээний хэмжээ"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Жишээ тутмын Bluetooth аудионы бит"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Bluetooth аудио кодлогч сонгох:\nЖишээ бүрт бит"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Bluetooth аудио сувгийн горим"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Bluetooth аудио кодлогч сонгох:\nСувгийн горим"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth Аудио LDAC Кодлогч: Тоглуулагчийн чанар"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Bluetooth Аудио 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_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi лог-н түвшинг нэмэгдүүлэх, Wi‑Fi Сонгогч дээрх SSID-д ногдох RSSI-г харуулах"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Идэвхжүүлсэн үед Wi‑Fi дохио сул бол дата холболтыг Үүрэн рүү шилжүүлэхдээ илүү идэвхтэй байх болно"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Тусламж, санал хүсэлт"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Цэс"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"Гринвичийн цаг"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Үйлдвэрийн тохиргоог демо горимд ажиллуулахын тулд нууц үг оруулна уу"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Дараагийн"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Нууц үг шаардлагатай"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml
index d8c8daf..f6ebf83 100644
--- a/packages/SettingsLib/res/values-mr/arrays.xml
+++ b/packages/SettingsLib/res/values-mr/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"केवळ DRM सामग्रीसाठी HDCP तपासणी वापरा"</item>
     <item msgid="45075631231212732">"नेहमी HDCP तपासणी वापरा"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"प्रणाली निवड वापरा (डीफॉल्ट)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX-HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"प्रणाली निवड वापरा (डीफॉल्ट)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX-HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"प्रणाली निवड वापरा (डीफॉल्ट)"</item>
+    <item msgid="8895532488906185219">"44.1 kHz"</item>
+    <item msgid="2909915718994807056">"48.0 kHz"</item>
+    <item msgid="3347287377354164611">"88.2 kHz"</item>
+    <item msgid="1234212100239985373">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"प्रणाली निवड वापरा (डीफॉल्ट)"</item>
+    <item msgid="4482862757811638365">"44.1 kHz"</item>
+    <item msgid="354495328188724404">"48.0 kHz"</item>
+    <item msgid="7329816882213695083">"88.2 kHz"</item>
+    <item msgid="6967397666254430476">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"प्रणाली निवड वापरा (डीफॉल्ट)"</item>
+    <item msgid="5618929009984956469">"16 बिट/नमुना"</item>
+    <item msgid="3412640499234627248">"24 बिट/नमुना"</item>
+    <item msgid="121583001492929387">"32 बिट/नमुना"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"प्रणाली निवड वापरा (डीफॉल्ट)"</item>
+    <item msgid="4726688794884191540">"16 बिट/नमुना"</item>
+    <item msgid="305344756485516870">"24 बिट/नमुना"</item>
+    <item msgid="244568657919675099">"32 बिट/नमुना"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"प्रणाली निवड वापरा (डीफॉल्ट)"</item>
+    <item msgid="4106832974775067314">"मोनो"</item>
+    <item msgid="5571632958424639155">"स्टिरिओ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"प्रणाली निवड वापरा (डीफॉल्ट)"</item>
+    <item msgid="8900559293912978337">"मोनो"</item>
+    <item msgid="8883739882299884241">"स्टिरिओ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"ऑडिओ गुणवत्तेसाठी (990kbps/909kbps) ऑप्टिमाइझ करा"</item>
+    <item msgid="2921767058740704969">"संतुलित ऑडिओ आणि कनेक्शन गुणवत्ता (660kbps/606kbps)"</item>
+    <item msgid="3682554248829489641">"कनेक्शन गुणवत्तेसाठी (330kbps/303kbps) ऑप्टिमाइझ करा"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"ऑडिओ गुणवत्तेसाठी ऑप्टिमाइझ करा"</item>
+    <item msgid="4327143584633311908">"संतुलित ऑडिओ आणि कनेक्शन गुणवत्ता"</item>
+    <item msgid="6155648878105378550">"कनेक्शन गुणवत्तेसाठी ऑप्टिमाइझ करा"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"बंद"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 6c012c8..a91ad45 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"सेल्युलर डेटा नेहमी सक्रिय"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"संपूर्ण आवाज अक्षम करा"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ब्लूटूथ ऑडिओ कोडेक"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Bluetooth ऑडिओ कोडेक निवडा"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"ब्लूटूथ ऑडिओ नमुना दर"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Bluetooth ऑडिओ कोडेक निवडा:\nनमुना दर"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"प्रति नमुना ब्लूटुथ ऑडिओ बिट"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Bluetooth ऑडिओ कोडेक निवडा:\nबिट प्रति नमुना"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"ब्लूटूथ ऑडिओ चॅनेल मोड"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Bluetooth ऑडिओ कोडेक निवडा:\nचॅनेल मोड"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth ऑडिओ LDAC कोडेक: प्लेबॅक गुणवत्ता"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Bluetooth ऑडिओ 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_verbose_logging_summary" msgid="6615071616111731958">"वाय-फाय लॉगिंग स्‍तर वाढवा, वाय-फाय निवडकामध्‍ये प्रति SSID RSSI दर्शवा"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"सक्षम केल्यास, वाय-फाय सिग्‍नल निम्‍न असताना, वाय-फाय डेटा कनेक्‍शन सेल्‍युलरवर बळपूर्वक स्विच करेल."</string>
@@ -360,4 +353,10 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"मदत आणि अभिप्राय"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"मेनू"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <!-- no translation found for retail_demo_reset_message (118771671364131297) -->
+    <skip />
+    <!-- no translation found for retail_demo_reset_next (8356731459226304963) -->
+    <skip />
+    <!-- no translation found for retail_demo_reset_title (696589204029930100) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index acaab9d..a3459772 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Bantuan &amp; maklum balas"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Mskkn kta laluan utk ttpn sml kilang dlm mod demo"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Seterusnya"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Kata laluan diperlukan"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-my/arrays.xml b/packages/SettingsLib/res/values-my/arrays.xml
index 9e71ae5..ddd0a64 100644
--- a/packages/SettingsLib/res/values-my/arrays.xml
+++ b/packages/SettingsLib/res/values-my/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"DRMအကြောင်းအရာအတွက် HDCPစစ်ဆေးခြင်းကိုသုံးမည်"</item>
     <item msgid="45075631231212732">"HDCP checkingအားအမြဲသုံးပါ"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item>
+    <item msgid="8895532488906185219">"၄၄.၁ kHz"</item>
+    <item msgid="2909915718994807056">"၄၈.၀ kHz"</item>
+    <item msgid="3347287377354164611">"၈၈.၂ kHz"</item>
+    <item msgid="1234212100239985373">"၉၆.၀ kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item>
+    <item msgid="4482862757811638365">"၄၄.၁ kHz"</item>
+    <item msgid="354495328188724404">"၄၈.၀ kHz"</item>
+    <item msgid="7329816882213695083">"၈၈.၂ kHz"</item>
+    <item msgid="6967397666254430476">"၉၆.၀ kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item>
+    <item msgid="5618929009984956469">"၁၆ bits/နမူနာ"</item>
+    <item msgid="3412640499234627248">"၂၄ bits/နမူနာ"</item>
+    <item msgid="121583001492929387">"၃၂ bits/နမူနာ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item>
+    <item msgid="4726688794884191540">"၁၆ bits/နမူနာ"</item>
+    <item msgid="305344756485516870">"၂၄ bits/နမူနာ"</item>
+    <item msgid="244568657919675099">"၃၂ bits/နမူနာ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item>
+    <item msgid="4106832974775067314">"မိုနို"</item>
+    <item msgid="5571632958424639155">"စတီရီယို"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"စနစ်ရွေးချယ်မှုကို အသုံးပြုပါ (မူရင်း)"</item>
+    <item msgid="8900559293912978337">"မိုနို"</item>
+    <item msgid="8883739882299884241">"စတီရီယို"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"အသံအရည်အသွေးကို ပိုကောင်းအောင် ပြုလုပ်ပေးသည် (၉၉၀kbps/၉၀၉kbps)"</item>
+    <item msgid="2921767058740704969">"အသံနှင့် ချိတ်ဆက်မှု အရည်အသွေးကို မျှတအောင် ချိန်ဆပေးသည် (၆၆၀kbps/၆၀၆kbps)"</item>
+    <item msgid="3682554248829489641">"ချိတ်ဆက်မှု အရည်အသွေးကို ပိုကောင်းအောင် ပြုလုပ်ပေးသည် (၃၃၀kbps/၃၀၃kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"အသံအရည်အသွေးကို ပိုကောင်းအောင် ပြုလုပ်ပေးသည်"</item>
+    <item msgid="4327143584633311908">"အသံနှင့် ချိတ်ဆက်မှု အရည်သွေးကို မျှတအောင် ချိန်ဆပေးသည်"</item>
+    <item msgid="6155648878105378550">"ချိတ်ဆက်မှု အရည်အသွေးကို ပိုကောင်းအောင် ပြုလုပ်ပေးသည်"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"ပိတ်ပါ"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 2c976d0..e2850ae 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"ဆဲလ်လူလာဒေတာ အမြဲတမ်းဖွင့်ထားသည်"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ပကတိ အသံနှုန်း သတ်မှတ်ချက် ပိတ်ရန်"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ဘလူးတုသ်အသံ ကိုးဒက်ခ်"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"ဘလူးတုသ်အသံကိုးဒက်ခ်ကို ရွေးပါ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"ဘလူးတုသ်အသံနမူနာနှုန်း"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"ဘလူးတုသ်အသံ ကိုးဒက်ခ်ကို ရွေးပါ−\nနမူနာနှုန်း"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"နမူနာတစ်ခုစီတွင် ပါဝင်သော ဘလူးတုသ်အသံပမာဏ Bits"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"ဘလူးတုသ်အသံ ကိုးဒက်ခ်ကို ရွေးပါ−\nနမူနာတစ်ခုချင်းအတွက် Bits"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"ဘလူးတုသ်အသံချန်နယ်မုဒ်"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"ဘလူးတုသ်အသံကိုးဒက်ခ်ကို ရွေးပါ−\nချန်နယ်မုဒ်"</string>
+    <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_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi မှတ်တမ်းတင်ခြင်း နှုန်းအားမြင့်ကာ၊ Wi‑Fi ရွေးရာတွင် SSID RSSI ဖြင့်ပြပါ"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"ဖွင့်ထားလျှင်၊ Wi‑Fi မှ ဆယ်လူလာသို့ အချက်လက် ချိတ်ဆက်မှုအား လွှဲပြောင်းရာ၌ ပိုမိုထိရောက်ပါသည်၊ WIFI အားနည်းနေချိန်တွင်"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"အကူအညီနှင့် အကြံပြုချက်"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"မီနူး"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"ဂရင်းနစ်စံတော်ချိန်"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"ဒီမိုမုဒ်၌နဂိုဆက်တင်ထားရန်စကားဝှက်ထည့်ပါ"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"ရှေ့သို့"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"စကားဝှက် လိုအပ်သည်"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml
index 1d5d098..bca999c 100644
--- a/packages/SettingsLib/res/values-nb/arrays.xml
+++ b/packages/SettingsLib/res/values-nb/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Bruk systemvalg (standard)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Bruk systemvalg (standard)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Bruk systemvalg (standard)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48,0 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Bruk systemvalg (standard)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48,0 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Bruk systemvalg (standard)"</item>
+    <item msgid="5618929009984956469">"16 bits/sample"</item>
+    <item msgid="3412640499234627248">"24 bits/sample"</item>
+    <item msgid="121583001492929387">"32 bits/sample"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Bruk systemvalg (standard)"</item>
+    <item msgid="4726688794884191540">"16 bits/sample"</item>
+    <item msgid="305344756485516870">"24 bits/sample"</item>
+    <item msgid="244568657919675099">"32 bits/sample"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Bruk systemvalg (standard)"</item>
+    <item msgid="4106832974775067314">"Mono"</item>
+    <item msgid="5571632958424639155">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Bruk systemvalg (standard)"</item>
+    <item msgid="8900559293912978337">"Mono"</item>
+    <item msgid="8883739882299884241">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Optimaliser for lydkvalitet (990 kbps/909 kbps)"</item>
+    <item msgid="2921767058740704969">"Balansert lyd- og tilkoblingskvalitet (660 kbps/606kbps)"</item>
+    <item msgid="3682554248829489641">"Optimaliser for tilkoblingskvalitet (330 kbps/303kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Optimaliser for lydkvalitet"</item>
+    <item msgid="4327143584633311908">"Balansert lyd- og tilkoblingskvalitet"</item>
+    <item msgid="6155648878105378550">"Optimaliser for tilkoblingskvalitet"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Av"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 02b742a..172d59c 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Mobildata er alltid aktiv"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Slå av funksjonen for absolutt volum"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Kodek for Bluetooth-lyd"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Velg kodek for Bluetooth-lyd"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Samplefrekvens for Bluetooth-lyd"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Velg kodek for Bluetooth-lyd:\nSamplefrekvens"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bits per sample for Bluetooth-lyd"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Velg lydkodek for Bluetooth:\nBits Per Sample"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Kanalmodus for Bluetooth-lyd"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Velg lydkodek for Bluetooth:\nKanalmodus"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"LDAC-kodek for Bluetooth-lyd: Avspillingskvalitet"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Velg LDAC-kodek for Bluetooth-lyd:\nAvspillingskvalitet"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Strømming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vis alternativer for sertifisering av trådløs skjerm"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Øk Wi-Fi-loggenivå – vis per SSID RSSI i Wi-Fi-velgeren"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Hvis dette slås på, overfører Wi-Fi-nettverket datatilkoblingen til mobil mer aggressivt når Wi-Fi-signalet er lavt"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Hjelp og tilbakemelding"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meny"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Skriv inn passordet for å tilbakestille til fabrikkstandard i demomodus"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Neste"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Passord er obligatorisk"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index 19597ec..ddde4e2 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"DRM सामग्रीको लागि मात्र HDCP जाँचको प्रयोग गर्नुहोस्"</item>
     <item msgid="45075631231212732">"सधैँ HDCP जाँच प्रयोग गर्नुहोस्"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item>
+    <item msgid="8895532488906185219">"४४.१ kHz"</item>
+    <item msgid="2909915718994807056">"४८.० kHz"</item>
+    <item msgid="3347287377354164611">"८८.२ kHz"</item>
+    <item msgid="1234212100239985373">"९६.० kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item>
+    <item msgid="4482862757811638365">"४४.१ kHz"</item>
+    <item msgid="354495328188724404">"४८.० kHz"</item>
+    <item msgid="7329816882213695083">"८८.२ kHz"</item>
+    <item msgid="6967397666254430476">"९६.० kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item>
+    <item msgid="5618929009984956469">"१६ बिट/नमूना"</item>
+    <item msgid="3412640499234627248">"२४ बिट/नमूना"</item>
+    <item msgid="121583001492929387">"३२ बिट/नमूना"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item>
+    <item msgid="4726688794884191540">"१६ बिट/नमूना"</item>
+    <item msgid="305344756485516870">"२४ बिट/नमूना"</item>
+    <item msgid="244568657919675099">"३२ बिट/नमूना"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item>
+    <item msgid="4106832974775067314">"मोनो"</item>
+    <item msgid="5571632958424639155">"स्टेरियो"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"प्रणालीको चयन प्रयोग गर्नुहोस् (पूर्वनिर्धारित)"</item>
+    <item msgid="8900559293912978337">"मोनो"</item>
+    <item msgid="8883739882299884241">"स्टेरियो"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"अडियोको गुणस्तर सुधार्न अनुकूलन गर्नुहोस् (९९०kbps/९०९kbps)"</item>
+    <item msgid="2921767058740704969">"सन्तुलित अडियो र जडान गुणस्तर (६६०kbps/६०६kbps)"</item>
+    <item msgid="3682554248829489641">"जडानको गुणस्तर सुधार्न अनुकूलन गर्नुहोस् (३३०kbps/३०३kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"अडियोको गुणस्तर सुधार्न अनुकूलन गर्नुहोस्"</item>
+    <item msgid="4327143584633311908">"सन्तुलित अडियो र जडान गुणस्तर"</item>
+    <item msgid="6155648878105378550">"जडानको गुणस्तर सुधार्न अनुकूलन गर्नुहोस्"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"निष्क्रिय गर्नुहोस्"</item>
     <item msgid="1593289376502312923">"६४के"</item>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 12b3b15..376fe9c 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"सेलुलर डेटा सधैं सक्रिय"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"निरपेक्ष आवाज असक्षम गर्नुहोस्"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ब्लुटुथ अडियोको कोडेक"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"ब्लुटुथ अडियोको कोडेक चयन गर्नुहोस्‌"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"ब्लुटुथ अडियोको नमूना दर"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"ब्लुटुथ अडियोको कोडेक चयन गर्नुहोस्‌:\nनमूना दर"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"प्रति नमूना ब्लुटुथ अडियोका बिटहरू"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"ब्लुटुथ अडियोको कोडेक चयन गर्नुहोस्‌:\n प्रति नमूना बिट"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"ब्लुटुथ अडियो च्यानलको मोड"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"ब्लुटुथ अडियोको कोडेक चयन गर्नुहोस्‌:\nच्यानलको मोड"</string>
+    <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_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi लग स्तर बढाउनुहोस्, Wi-Fi चयनकर्तामा प्रति SSID RSSI देखाइन्छ"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Wi-Fi संकेत कम हुँदा, सक्षम जब गरिन्छ, Wi-Fi सेलुलर लागि डेटा जडान सुम्पनामा बढी आक्रामक हुनेछ"</string>
@@ -360,4 +353,10 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"मद्दत र प्रतिक्रिया"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"मेनु"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <!-- no translation found for retail_demo_reset_message (118771671364131297) -->
+    <skip />
+    <!-- no translation found for retail_demo_reset_next (8356731459226304963) -->
+    <skip />
+    <!-- no translation found for retail_demo_reset_title (696589204029930100) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-nl/arrays.xml b/packages/SettingsLib/res/values-nl/arrays.xml
index eaa8402..e1822c6 100644
--- a/packages/SettingsLib/res/values-nl/arrays.xml
+++ b/packages/SettingsLib/res/values-nl/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"HDCP-controle alleen voor DRM-content gebruiken"</item>
     <item msgid="45075631231212732">"HDCP-controle altijd gebruiken"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Systeemselectie gebruiken (standaard)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Systeemselectie gebruiken (standaard)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Systeemselectie gebruiken (standaard)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48,0 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Systeemselectie gebruiken (standaard)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48,0 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Systeemselectie gebruiken (standaard)"</item>
+    <item msgid="5618929009984956469">"16 bits per sample"</item>
+    <item msgid="3412640499234627248">"24 bits per sample"</item>
+    <item msgid="121583001492929387">"32 bits per sample"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Systeemselectie gebruiken (standaard)"</item>
+    <item msgid="4726688794884191540">"16 bits per sample"</item>
+    <item msgid="305344756485516870">"24 bits per sample"</item>
+    <item msgid="244568657919675099">"32 bits per sample"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Systeemselectie gebruiken (standaard)"</item>
+    <item msgid="4106832974775067314">"Mono"</item>
+    <item msgid="5571632958424639155">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Systeemselectie gebruiken (standaard)"</item>
+    <item msgid="8900559293912978337">"Mono"</item>
+    <item msgid="8883739882299884241">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Optimaliseren voor audiokwaliteit (990 kbps/909 kbps)"</item>
+    <item msgid="2921767058740704969">"Gebalanceerde audio- en verbindingskwaliteit (660 kbps/606 kbps)"</item>
+    <item msgid="3682554248829489641">"Optimaliseren voor verbindingskwaliteit (330 kbps/303 kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Optimaliseren voor audiokwaliteit"</item>
+    <item msgid="4327143584633311908">"Gebalanceerde audio- en verbindingskwaliteit"</item>
+    <item msgid="6155648878105378550">"Optimaliseren voor verbindingskwaliteit"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Uit"</item>
     <item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 9d53379..30439710 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Mobiele data altijd actief"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Absoluut volume uitschakelen"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth-audiocodec"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Bluetooth-audiocodec selecteren"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bemonsteringsfrequentie (sample rate) van Bluetooth-audio"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Bluetooth-audiocodec selecteren:\nbemonsteringsfrequentie"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bits per sample voor Bluetooth-audio"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Bluetooth-audiocodec selecteren:\nbit per sample"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Kanaalmodus voor Bluetooth-audio"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Bluetooth-audiocodec selecteren:\nkanaalmodus"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"LDAC-codec voor Bluetooth-audio: afspeelkwaliteit"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"LDAC-codec voor Bluetooth-audio selecteren:\nafspeelkwaliteit"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streaming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Opties weergeven voor certificering van draadloze weergave"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Logniveau voor wifi verhogen, weergeven per SSID RSSI in wifi-kiezer"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Indien ingeschakeld, is wifi agressiever bij het overgeven van de gegevensverbinding aan mobiel wanneer het wifi-signaal zwak is"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Help en feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Geef wachtwoord op om terug te zetten op fabrieksinstellingen in demomodus"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Volgende"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Wachtwoord vereist"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pa/arrays.xml b/packages/SettingsLib/res/values-pa/arrays.xml
index 7a100a9..ed44102 100644
--- a/packages/SettingsLib/res/values-pa/arrays.xml
+++ b/packages/SettingsLib/res/values-pa/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"ਕੇਵਲ DRM ਸਮੱਗਰੀ ਲਈ HDCP ਜਾਂਚ"</item>
     <item msgid="45075631231212732">"ਹਮੇਸਾਂ HDCP ਜਾਂਚ ਵਰਤੋ"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
+    <item msgid="8895532488906185219">"44.1 kHz"</item>
+    <item msgid="2909915718994807056">"48.0 kHz"</item>
+    <item msgid="3347287377354164611">"88.2 kHz"</item>
+    <item msgid="1234212100239985373">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
+    <item msgid="4482862757811638365">"44.1 kHz"</item>
+    <item msgid="354495328188724404">"48.0 kHz"</item>
+    <item msgid="7329816882213695083">"88.2 kHz"</item>
+    <item msgid="6967397666254430476">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
+    <item msgid="5618929009984956469">"16 ਬਿਟਾਂ/ਨਮੂਨਾ"</item>
+    <item msgid="3412640499234627248">"24 ਬਿਟਾਂ/ਨਮੂਨਾ"</item>
+    <item msgid="121583001492929387">"32 ਬਿਟਾਂ/ਨਮੂਨਾ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
+    <item msgid="4726688794884191540">"16 ਬਿਟਾਂ/ਨਮੂਨਾ"</item>
+    <item msgid="305344756485516870">"24 ਬਿਟਾਂ/ਨਮੂਨਾ"</item>
+    <item msgid="244568657919675099">"32 ਬਿਟਾਂ/ਨਮੂਨਾ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
+    <item msgid="4106832974775067314">"ਮੋਨੋ"</item>
+    <item msgid="5571632958424639155">"ਸਟੀਰੀਓ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"ਸਿਸਟਮ ਚੋਣ ਦੀ ਵਰਤੋਂ ਕਰੋ (ਪੂਰਵ-ਨਿਰਧਾਰਤ)"</item>
+    <item msgid="8900559293912978337">"ਮੋਨੋ"</item>
+    <item msgid="8883739882299884241">"ਸਟੀਰੀਓ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"ਔਡੀਓ ਗੁਣਵੱਤਾ ਨੂੰ ਵਧਾਓ (990kbps/909kbps)"</item>
+    <item msgid="2921767058740704969">"ਬੈਲੈਂਸਡ ਔਡੀਓ ਅਤੇ ਕਨੈਕਸ਼ਨ ਗੁਣਵੱਤਾ (660kbps/606kbps)"</item>
+    <item msgid="3682554248829489641">"ਕਨੈਕਸ਼ਨ ਗੁਣਵੱਤਾ ਨੂੰ ਵਧਾਓ (330kbps/303kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"ਔਡੀਓ ਗੁਣਵੱਤਾ ਨੂੰ ਵਧਾਓ"</item>
+    <item msgid="4327143584633311908">"ਬੈਲੈਂਸਡ ਔਡੀਓ ਅਤੇ ਕਨੈਕਸ਼ਨ ਗੁਣਵੱਤਾ"</item>
+    <item msgid="6155648878105378550">"ਕਨੈਕਸ਼ਨ ਗੁਣਵੱਤਾ ਨੂੰ ਵਧਾਓ"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"ਬੰਦ"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 647e573..f7a95cd 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"ਸੈਲਿਊਲਰ ਡੇਟਾ ਹਮੇਸ਼ਾ ਕਿਰਿਆਸ਼ੀਲ"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ਪੂਰਨ ਵੌਲਿਊਮ ਨੂੰ ਅਯੋਗ ਬਣਾਓ"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ਬਲੂਟੁੱਥ ਔਡੀਓ ਕੋਡੇਕ"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"ਬਲੂਟੁੱਥ ਔਡੀਓ ਕੋਡੇਕ ਚੁਣੋ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"ਬਲੂਟੁੱਥ ਔਡੀਓ ਨਮੂਨਾ ਦਰ"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"ਬਲੂਟੁੱਥ ਔਡੀਓ ਕੋਡੇਕ ਚੁਣੋ:\nਨਮੂਨਾ ਗਤੀ"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"ਪ੍ਰਤੀ ਨਮੂਨਾ ਬਲੂਟੁੱਥ ਔਡੀਓ ਬਿਟਾਂ"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"ਬਲੂਟੁੱਥ ਔਡੀਓ ਕੋਡੇਕ ਚੁਣੋ:\nਬਿਟਾਂ ਪ੍ਰਤੀ ਨਮੂਨਾ"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"ਬਲੂਟੁੱਥ ਔਡੀਓ ਚੈਨਲ ਮੋਡ"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"ਬਲੂਟੁੱਥ ਔਡੀਓ ਕੋਡੇਕ ਚੁਣੋ:\nਚੈਨਲ ਮੋਡ"</string>
+    <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_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ਲੌਗਿੰਗ ਪੱਧਰ ਵਧਾਓ, Wi‑Fi Picker ਵਿੱਚ ਪ੍ਰਤੀ SSID RSSI ਦਿਖਾਓ"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"ਜਦੋਂ ਸਮਰਥਿਤ ਹੋਵੇ, ਤਾਂ Wi‑Fi ਸੈਲਿਊਲਰ ਨੂੰ ਡੈਟਾ ਕਨੈਕਸ਼ਨ ਹੈਂਡ ਓਵਰ ਕਰਨ ਵਿੱਚ ਵੱਧ ਅਗ੍ਰੈਸਿਵ ਹੋ ਜਾਏਗਾ, ਜਦੋਂ Wi‑Fi ਸਿਗਨਲ ਘੱਟ ਹੋਵੇ"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"ਮਦਦ ਅਤੇ ਪ੍ਰਤੀਕਰਮ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"ਮੀਨੂ"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"ਡੈਮੋ ਮੋਡ \'ਚ ਫੈਕਟਰੀ ਰੀਸੈੱਟ ਲਈ ਪਾਸਵਰਡ ਦਿਓ"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"ਅੱਗੇ"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"ਪਾਸਵਰਡ ਦੀ ਲੋੜ ਹੈ"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 20cb365..1c5f3d2 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Pomoc i opinie"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Wpisz hasło, by przywrócić ustawienia fabryczne w trybie demonstracyjnym"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Dalej"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Wymagane hasło"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
index 29e3f41..e238905 100644
--- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Usar seleção do sistema (padrão)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Usar seleção do sistema (padrão)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Usar seleção do sistema (padrão)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Usar seleção do sistema (padrão)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Usar seleção do sistema (padrão)"</item>
+    <item msgid="5618929009984956469">"16 bits/amostra"</item>
+    <item msgid="3412640499234627248">"24 bits/amostra"</item>
+    <item msgid="121583001492929387">"32 bits/amostra"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Usar seleção do sistema (padrão)"</item>
+    <item msgid="4726688794884191540">"16 bits/amostra"</item>
+    <item msgid="305344756485516870">"24 bits/amostra"</item>
+    <item msgid="244568657919675099">"32 bits/amostra"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Usar seleção do sistema (padrão)"</item>
+    <item msgid="4106832974775067314">"Mono"</item>
+    <item msgid="5571632958424639155">"Estéreo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Usar seleção do sistema (padrão)"</item>
+    <item msgid="8900559293912978337">"Mono"</item>
+    <item msgid="8883739882299884241">"Estéreo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Otimizar para qualidade de áudio (990 kbps/909 kbps)"</item>
+    <item msgid="2921767058740704969">"Qualidade de áudio e de conexão balanceada (660 kbps/606 kbps)"</item>
+    <item msgid="3682554248829489641">"Otimizar para qualidade da conexão (330 kbps/303 kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Otimizar para qualidade de áudio"</item>
+    <item msgid="4327143584633311908">"Qualidade de áudio e de conexão balanceada"</item>
+    <item msgid="6155648878105378550">"Otimizar para qualidade de conexão"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Desativado"</item>
     <item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 5ad3cd9e..dcbac24 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Dados da rede celular sempre ativos"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desativar volume absoluto"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec de áudio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Selecionar codec de áudio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Taxa de amostra do áudio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Selecionar codec de áudio Bluetooth:\ntaxa de amostragem"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bits por amostra do áudio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Selecionar codec de áudio Bluetooth:\nbits por amostra"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Modo de canal de áudio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Selecionar codec de áudio Bluetooth:\nmodo de canal"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Codec de áudio Bluetooth LDAC: qualidade de reprodução"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Selecionar codec de áudio Bluetooth LDAC:\nqualidade de reprodução"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streaming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções de certificação de Display sem fio"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nível de registro do Wi-Fi; mostrar conforme o RSSI de SSID na Seleção de Wi-Fi"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Quando ativada, o Wi-Fi será mais agressivo em transferir a conexão de dados para celular, quando o sinal de Wi-Fi estiver fraco"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Ajuda e feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Digite a senha para redef. p/ configuração original em modo demo"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Próxima"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Senha necessária"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/arrays.xml b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
index cf4d1c8..048c727 100644
--- a/packages/SettingsLib/res/values-pt-rPT/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Utilizar seleção do sistema (predef.)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Utilizar seleção do sistema (predef.)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Utilizar seleção do sistema (predef.)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48,0 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Utilizar seleção do sistema (predef.)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48,0 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Utilizar seleção do sistema (predef.)"</item>
+    <item msgid="5618929009984956469">"16 bits/amostra"</item>
+    <item msgid="3412640499234627248">"24 bits/amostra"</item>
+    <item msgid="121583001492929387">"32 bits/amostra"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Utilizar seleção do sistema (predef.)"</item>
+    <item msgid="4726688794884191540">"16 bits/amostra"</item>
+    <item msgid="305344756485516870">"24 bits/amostra"</item>
+    <item msgid="244568657919675099">"32 bits/amostra"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Utilizar seleção do sistema (predef.)"</item>
+    <item msgid="4106832974775067314">"Mono"</item>
+    <item msgid="5571632958424639155">"Estéreo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Utilizar seleção do sistema (predef.)"</item>
+    <item msgid="8900559293912978337">"Mono"</item>
+    <item msgid="8883739882299884241">"Estéreo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Otimizar para qualidade de áudio (990 kbps/909 kbps)"</item>
+    <item msgid="2921767058740704969">"Qualidade de áudio e de ligação equilibrada (660 kbps/606 kbps)"</item>
+    <item msgid="3682554248829489641">"Otimizar para qualidade de ligação (330 kbps/303 kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Otimizar para qualidade de áudio"</item>
+    <item msgid="4327143584633311908">"Qualidade de áudio e de ligação equilibrada"</item>
+    <item msgid="6155648878105378550">"Otimizar para qualidade de ligação"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Desativado"</item>
     <item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index f8ceac2..3163ce4 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Dados móveis sempre ativados"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desativar volume absoluto"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec de áudio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Selecionar codec de áudio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Taxa de amostragem de áudio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Selecionar codec de áudio Bluetooth:\nTaxa de amostragem"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bits por amostra de áudio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Selecionar codec de áudio Bluetooth:\nBits por amostra"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Modo de canal áudio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Selecionar codec de áudio de Bluetooth:\nModo de canal"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Codec LDAC de áudio Bluetooth: qualidade de reprodução"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Selecionar codec LDAC de áudio Bluetooth:\nQualidade de reprodução"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Transmissão em fluxo contínuo: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções da certificação de display sem fios"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nível de reg. de Wi-Fi, mostrar por RSSI de SSID no Selec. de Wi-Fi"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Se estiver ativado, o Wi-Fi será mais agressivo ao transmitir a lig. de dados p/ a rede móvel quando o sinal Wi-Fi estiver fraco"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Ajuda e comentários"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Intr. palavra-passe p/ repos. fábrica no modo demo"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Próximo"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Palavra-passe obrigatória"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml
index 29e3f41..e238905 100644
--- a/packages/SettingsLib/res/values-pt/arrays.xml
+++ b/packages/SettingsLib/res/values-pt/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Usar seleção do sistema (padrão)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Usar seleção do sistema (padrão)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Usar seleção do sistema (padrão)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Usar seleção do sistema (padrão)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Usar seleção do sistema (padrão)"</item>
+    <item msgid="5618929009984956469">"16 bits/amostra"</item>
+    <item msgid="3412640499234627248">"24 bits/amostra"</item>
+    <item msgid="121583001492929387">"32 bits/amostra"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Usar seleção do sistema (padrão)"</item>
+    <item msgid="4726688794884191540">"16 bits/amostra"</item>
+    <item msgid="305344756485516870">"24 bits/amostra"</item>
+    <item msgid="244568657919675099">"32 bits/amostra"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Usar seleção do sistema (padrão)"</item>
+    <item msgid="4106832974775067314">"Mono"</item>
+    <item msgid="5571632958424639155">"Estéreo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Usar seleção do sistema (padrão)"</item>
+    <item msgid="8900559293912978337">"Mono"</item>
+    <item msgid="8883739882299884241">"Estéreo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Otimizar para qualidade de áudio (990 kbps/909 kbps)"</item>
+    <item msgid="2921767058740704969">"Qualidade de áudio e de conexão balanceada (660 kbps/606 kbps)"</item>
+    <item msgid="3682554248829489641">"Otimizar para qualidade da conexão (330 kbps/303 kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Otimizar para qualidade de áudio"</item>
+    <item msgid="4327143584633311908">"Qualidade de áudio e de conexão balanceada"</item>
+    <item msgid="6155648878105378550">"Otimizar para qualidade de conexão"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Desativado"</item>
     <item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 5ad3cd9e..dcbac24 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Dados da rede celular sempre ativos"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Desativar volume absoluto"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec de áudio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Selecionar codec de áudio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Taxa de amostra do áudio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Selecionar codec de áudio Bluetooth:\ntaxa de amostragem"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bits por amostra do áudio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Selecionar codec de áudio Bluetooth:\nbits por amostra"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Modo de canal de áudio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Selecionar codec de áudio Bluetooth:\nmodo de canal"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Codec de áudio Bluetooth LDAC: qualidade de reprodução"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Selecionar codec de áudio Bluetooth LDAC:\nqualidade de reprodução"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streaming: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções de certificação de Display sem fio"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nível de registro do Wi-Fi; mostrar conforme o RSSI de SSID na Seleção de Wi-Fi"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Quando ativada, o Wi-Fi será mais agressivo em transferir a conexão de dados para celular, quando o sinal de Wi-Fi estiver fraco"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Ajuda e feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Digite a senha para redef. p/ configuração original em modo demo"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Próxima"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Senha necessária"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index dc03065..e801213 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Folosiți selectarea sist. (prestabilit)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Folosiți selectarea sist. (prestabilit)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Folosiți selectarea sist. (prestabilit)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48,0 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Folosiți selectarea sist. (prestabilit)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48,0 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Folosiți selectarea sist. (prestabilit)"</item>
+    <item msgid="5618929009984956469">"16 biți/eșantion"</item>
+    <item msgid="3412640499234627248">"24 biți/eșantion"</item>
+    <item msgid="121583001492929387">"32 biți/eșantion"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Folosiți selectarea sist. (prestabilit)"</item>
+    <item msgid="4726688794884191540">"16 biți/eșantion"</item>
+    <item msgid="305344756485516870">"24 biți/eșantion"</item>
+    <item msgid="244568657919675099">"32 biți/eșantion"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Folosiți selectarea sist. (prestabilit)"</item>
+    <item msgid="4106832974775067314">"Mono"</item>
+    <item msgid="5571632958424639155">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Folosiți selectarea sist. (prestabilit)"</item>
+    <item msgid="8900559293912978337">"Mono"</item>
+    <item msgid="8883739882299884241">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Optimizați pentru calitatea audio (990 kbps/909 kbps)"</item>
+    <item msgid="2921767058740704969">"Calitatea audio și a conexiunii echilibrată (660 kbps/606 kbps)"</item>
+    <item msgid="3682554248829489641">"Optimizați pentru calitatea conexiunii (330 kbps/303 kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Optimizați pentru calitatea audio"</item>
+    <item msgid="4327143584633311908">"Calitatea audio și a conexiunii echilibrată"</item>
+    <item msgid="6155648878105378550">"Optimizați pentru calitatea conexiunii"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Dezactivată"</item>
     <item msgid="1593289376502312923">"64 KB"</item>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 8714926..bae40ef 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Conexiunea de date mobile este întotdeauna activată"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Dezactivați volumul absolut"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec audio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Selectați codecul audio Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Rată de eșantionare audio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Selectați codecul audio Bluetooth:\nrată de eșantionare"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Biți audio Bluetooth per eșantion"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Selectați codecul audio Bluetooth:\nbiți per eșantion"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Modul canal audio Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Selectați codecul audio Bluetooth:\nmodul canal"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Codecul LDAC audio pentru Bluetooth: calitatea redării"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Selectați codecul LDAC audio pentru Bluetooth:\ncalitatea redării"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Transmitere în flux: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afișați opțiunile pentru certificarea Ecran wireless"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Măriți niv. de înr. prin Wi‑Fi, afișați în fcț. de SSID RSSI în Selectorul Wi‑Fi"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Când este activată, funcția Wi-Fi va fi mai agresivă la predarea conexiunii de date către mobil când semnalul Wi-Fi este slab"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Ajutor și feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meniu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Intr. par. pt. a rev. set. fab. în demo"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Înainte"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Trebuie să introduceți o parolă"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ru/arrays.xml b/packages/SettingsLib/res/values-ru/arrays.xml
index bf192a5..6cc82a2 100644
--- a/packages/SettingsLib/res/values-ru/arrays.xml
+++ b/packages/SettingsLib/res/values-ru/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"Использовать проверку HDCP только для DRM-контента"</item>
     <item msgid="45075631231212732">"Всегда использовать проверку HDCP"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Выбор системы (по умолчанию)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Выбор системы (по умолчанию)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Выбор системы (по умолчанию)"</item>
+    <item msgid="8895532488906185219">"44,1 кГц"</item>
+    <item msgid="2909915718994807056">"48 кГц"</item>
+    <item msgid="3347287377354164611">"88,2 кГц"</item>
+    <item msgid="1234212100239985373">"96 кГц"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Выбор системы (по умолчанию)"</item>
+    <item msgid="4482862757811638365">"44,1 кГц"</item>
+    <item msgid="354495328188724404">"48 кГц"</item>
+    <item msgid="7329816882213695083">"88,2 кГц"</item>
+    <item msgid="6967397666254430476">"96 кГц"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Выбор системы (по умолчанию)"</item>
+    <item msgid="5618929009984956469">"16 бит/отсчет"</item>
+    <item msgid="3412640499234627248">"24 бит/отсчет"</item>
+    <item msgid="121583001492929387">"32 бит/отсчет"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Выбор системы (по умолчанию)"</item>
+    <item msgid="4726688794884191540">"16 бит/отсчет"</item>
+    <item msgid="305344756485516870">"24 бит/отсчет"</item>
+    <item msgid="244568657919675099">"32 бит/отсчет"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Выбор системы (по умолчанию)"</item>
+    <item msgid="4106832974775067314">"Моно"</item>
+    <item msgid="5571632958424639155">"Стерео"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Выбор системы (по умолчанию)"</item>
+    <item msgid="8900559293912978337">"Моно"</item>
+    <item msgid="8883739882299884241">"Стерео"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Оптимизация под качество аудио (990/909 кбит/с)"</item>
+    <item msgid="2921767058740704969">"Баланс качества аудио и скорости подключения (660/606 кбит/с)"</item>
+    <item msgid="3682554248829489641">"Оптимизация под скорость подключения (330/303 кбит/с)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Оптимизация под качество аудио"</item>
+    <item msgid="4327143584633311908">"Баланс качества аудио и скорости подключения"</item>
+    <item msgid="6155648878105378550">"Оптимизация под скорость подключения"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Выкл."</item>
     <item msgid="1593289376502312923">"64 КБ"</item>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 9da906b..df69f91 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Не отключать передачу данных"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Отключить абсолютный уровень громкости"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Аудиокодек для передачи через Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Аудиокодек для передачи через Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Частота дискретизации при передаче через Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Аудиокодек для передачи через Bluetooth:\nчастота дискретизации"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Глубина кодирования звука при передаче через Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Аудиокодек для передачи через Bluetooth:\nбитов на образец"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Режим аудиоканала Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Аудиокодек для передачи через Bluetooth:\nрежим канала"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Качество воспроизведения с аудиокодеком LDAC (через Bluetooth)"</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_verbose_logging_summary" msgid="6615071616111731958">"При выборе Wi‑Fi указывать в журнале RSSI для каждого SSID"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Принудительно переключаться на мобильную сеть, если сигнал Wi-Fi слабый"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Справка/отзыв"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Меню"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Чтобы сбросить настройки в деморежиме, введите пароль."</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Далее"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Требуется пароль"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 1ff81e6..bfe1e9b 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"උදව් සහ ප්‍රතිපෝෂණ"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"මෙනුව"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"ආදර්ශන ප්‍රකාර කර්මාන්තශාලා යළි සැකසීමට මුරපදය ඇ. ක."</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"ඊළඟ"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"මුරපදය අවශ්‍යයි"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml
index 3dd56cb..178388e 100644
--- a/packages/SettingsLib/res/values-sk/arrays.xml
+++ b/packages/SettingsLib/res/values-sk/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Použiť voľbu systému (predvolené)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Použiť voľbu systému (predvolené)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Použiť voľbu systému (predvolené)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48,0 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Použiť voľbu systému (predvolené)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48,0 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Použiť voľbu systému (predvolené)"</item>
+    <item msgid="5618929009984956469">"16 bitov na vzorku"</item>
+    <item msgid="3412640499234627248">"24 bitov na vzorku"</item>
+    <item msgid="121583001492929387">"32 bitov na vzorku"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Použiť voľbu systému (predvolené)"</item>
+    <item msgid="4726688794884191540">"16 bitov na vzorku"</item>
+    <item msgid="305344756485516870">"24 bitov na vzorku"</item>
+    <item msgid="244568657919675099">"32 bitov na vzorku"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Použiť voľbu systému (predvolené)"</item>
+    <item msgid="4106832974775067314">"Mono"</item>
+    <item msgid="5571632958424639155">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Použiť voľbu systému (predvolené)"</item>
+    <item msgid="8900559293912978337">"Mono"</item>
+    <item msgid="8883739882299884241">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Optimalizovať na kvalitu zvuku (990/909 kb/s)"</item>
+    <item msgid="2921767058740704969">"Vyrovnaná kvalita zvuku a pripojenia (660/606 kb/s)"</item>
+    <item msgid="3682554248829489641">"Optimalizovať na kvalitu pripojenia (330/303 kb/s)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Optimalizovať na kvalitu zvuku"</item>
+    <item msgid="4327143584633311908">"Vyrovnaná kvalita zvuku a pripojenia"</item>
+    <item msgid="6155648878105378550">"Optimalizovať na kvalitu pripojenia"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Vypnuté"</item>
     <item msgid="1593289376502312923">"64 kB"</item>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index dfdc8f1..ce1315a 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Mobilné dáta vždy aktívne"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Zakázať absolútnu hlasitosť"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth Audio – kodek"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Vybrať kodek Bluetooth Audio"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bluetooth Audio – vzorkovacia frekvencia"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Vybrať kodek Bluetooth Audio:\nVzorkovacia frekvencia"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bluetooth Audio – počet bitov na vzorku"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Vybrať kodek Bluetooth Audio:\nPočet bitov na vzorku"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Bluetooth Audio – režim kanála"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Vybrať kodek Bluetooth Audio:\nRežim kanála"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Kodek LDAC Bluetooth Audio: Kvalita prehrávania"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Vybrať kodek LDAC Bluetooth Audio:\nKvalita prehrávania"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Streamovanie: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Zobraziť možnosti certifikácie bezdrôtového zobrazenia"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Zvýšiť úroveň denníkov Wi-Fi, zobrazovať podľa SSID RSSI pri výbere siete Wi-Fi"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Keď túto možnosť zapnete, Wi-Fi bude agresívnejšie odovzdávať dát. pripoj. na mob. sieť vtedy, keď bude slabý signál Wi-Fi"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Pomocník a spätná väzba"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Ponuka"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Zadajte heslo na obnovenie továrenských nastavení v režime ukážky"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Ďalej"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Vyžaduje sa heslo"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index af564f8..eb80a30 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Pomoč in povratne informacije"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meni"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Geslo za tovar. nast. v predstav. načinu"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Naprej"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Vnesite geslo"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sq/arrays.xml b/packages/SettingsLib/res/values-sq/arrays.xml
index b91f694..29f27a4 100644
--- a/packages/SettingsLib/res/values-sq/arrays.xml
+++ b/packages/SettingsLib/res/values-sq/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48,0 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48,0 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item>
+    <item msgid="5618929009984956469">"16 bite/shembull"</item>
+    <item msgid="3412640499234627248">"24 bite/shembull"</item>
+    <item msgid="121583001492929387">"32 bite/shembull"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item>
+    <item msgid="4726688794884191540">"16 bite/shembull"</item>
+    <item msgid="305344756485516870">"24 bite/shembull"</item>
+    <item msgid="244568657919675099">"32 bite/shembull"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item>
+    <item msgid="4106832974775067314">"Mono"</item>
+    <item msgid="5571632958424639155">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Përdor përzgjedhjen e sistemit (e parazgjedhur)"</item>
+    <item msgid="8900559293912978337">"Mono"</item>
+    <item msgid="8883739882299884241">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Optimizoje për cilësi audioje (990 kbps/909 kbps)"</item>
+    <item msgid="2921767058740704969">"Cilësi e balancuar e audios dhe e lidhjes (660 kbps/606 kbps)"</item>
+    <item msgid="3682554248829489641">"Optimizoje për cilësi lidhjeje (330 kbps/303 kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Optimizoje për cilësi audioje"</item>
+    <item msgid="4327143584633311908">"Cilësi e balancuar e audios dhe e lidhjes"</item>
+    <item msgid="6155648878105378550">"Optimizoje për cilësi lidhjeje"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Joaktiv"</item>
     <item msgid="1593289376502312923">"64 mijë"</item>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 1017cfc..7163852 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Të dhënat celulare gjithmonë aktive"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Çaktivizo volumin absolut"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Kodeku Bluetooth Audio"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Zgjidh kodekun e audios së Bluetooth-it"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Shpejtësia e shembullit të Bluetooth Audio"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Zgjidh kodekun e audios së Bluetooth-it:\nShpejtësia e shembullit"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bite për shembull Bluetooth Audio"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Zgjidh kodekun e audios së Bluetooth-it:\nBite për shembull"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Regjimi i kanalit Bluetooth Audio"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Zgjidh kodekun e audios së Bluetooth-it:\nModaliteti i kanalit"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Kodeku LDAC i audios së Bluetooth-it: Cilësia e luajtjes"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Zgjidh kodekun LDAC të audios së Bluetooth-it:\nCilësia e luajtjes"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Transmetimi: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Shfaq opsionet për certifikimin e ekranit valor"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Rrit nivelin regjistrues të Wi‑Fi duke shfaqur SSID RSSI-në te Zgjedhësi i Wi‑Fi"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Kur ky funksion aktivizohet, Wi‑Fi bëhet më agresiv në kalimin e lidhjes së të dhënave te rrjeti celular, në rastet kur sinjali Wi‑Fi është i dobët"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Ndihma dhe komentet"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menyja"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Fut fjalëkalimin për të kryer rivendosje në gjendje fabrike në modalitetin e demonstrimit"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Përpara"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Kërkohet fjalëkalimi"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sr/arrays.xml b/packages/SettingsLib/res/values-sr/arrays.xml
index e767145..6956bb8 100644
--- a/packages/SettingsLib/res/values-sr/arrays.xml
+++ b/packages/SettingsLib/res/values-sr/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"Користи HDCP проверу само за DRM садржај"</item>
     <item msgid="45075631231212732">"Увек користи HDCP проверу"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Користи избор система (подразумевано)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Користи избор система (подразумевано)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Користи избор система (подразумевано)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48,0 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Користи избор система (подразумевано)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48,0 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Користи избор система (подразумевано)"</item>
+    <item msgid="5618929009984956469">"16 битова по узорку"</item>
+    <item msgid="3412640499234627248">"24 бита по узорку"</item>
+    <item msgid="121583001492929387">"32 бита по узорку"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Користи избор система (подразумевано)"</item>
+    <item msgid="4726688794884191540">"16 битова по узорку"</item>
+    <item msgid="305344756485516870">"24 бита по узорку"</item>
+    <item msgid="244568657919675099">"32 бита по узорку"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Користи избор система (подразумевано)"</item>
+    <item msgid="4106832974775067314">"Моно"</item>
+    <item msgid="5571632958424639155">"Стерео"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Користи избор система (подразумевано)"</item>
+    <item msgid="8900559293912978337">"Моно"</item>
+    <item msgid="8883739882299884241">"Стерео"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Оптимизуј за квалитет звука (990 kb/s/909 kb/s)"</item>
+    <item msgid="2921767058740704969">"Уједначен квалитет звука и везе (660 kb/s/606 kb/s)"</item>
+    <item msgid="3682554248829489641">"Оптимизуј за квалитет везе (330 kb/s/303 kb/s)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Оптимизује се за квалитет звука"</item>
+    <item msgid="4327143584633311908">"Уједначен квалитет звука и везе"</item>
+    <item msgid="6155648878105378550">"Оптимизује се за квалитет везе"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Искључено"</item>
     <item msgid="1593289376502312923">"64 kB"</item>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index f6de46b..7ea3bf3 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Подаци за мобилне уређаје су увек активни"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Онемогући главно подешавање јачине звука"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth аудио кодек"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Изаберите Bluetooth аудио кодек"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Брзина узорковања за Bluetooth аудио"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Изаберите Bluetooth аудио кодек:\nбрзина узорковања"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Битова по узорку за Bluetooth аудио"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Изаберите Bluetooth аудио кодек:\nбитова по узорку"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Режим канала за Bluetooth аудио"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Изаберите Bluetooth аудио кодек:\nрежим канала"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Bluetooth аудио кодек LDAC: квалитет репродукције"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Изаберите Bluetooth аудио кодек 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_verbose_logging_summary" msgid="6615071616111731958">"Повећава ниво евидентирања за Wi‑Fi. Приказ по SSID RSSI-у у бирачу Wi‑Fi мреже"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Када се омогући, Wi‑Fi ће бити агресивнији при пребацивању мреже за пренос података на Мобилну, када је Wi‑Fi сигнал слаб"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Помоћ и повратне информације"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Мени"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Унесите лозинку да бисте обавили ресетовање на фабричка подешавања у режиму демонстрације"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Даље"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Потребна је лозинка"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index d68580b..9e4ad29 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Hjälp och feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Meny"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Ange lösenord och utför fabriksåterställning i demoläge"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Nästa"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Lösenord krävs"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml
index a7c4b63..66d65c9 100644
--- a/packages/SettingsLib/res/values-sw/arrays.xml
+++ b/packages/SettingsLib/res/values-sw/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Tumia Uteuzi wa Mfumo (Chaguo-msingi)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Tumia Uteuzi wa Mfumo (Chaguo-msingi)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Tumia Uteuzi wa Mfumo (Chaguo-msingi)"</item>
+    <item msgid="8895532488906185219">"kHz 44.1"</item>
+    <item msgid="2909915718994807056">"kHz 48.0"</item>
+    <item msgid="3347287377354164611">"kHz 88.2"</item>
+    <item msgid="1234212100239985373">"kHz 96.0"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Tumia Uteuzi wa Mfumo (Chaguo-msingi)"</item>
+    <item msgid="4482862757811638365">"kHz 44.1"</item>
+    <item msgid="354495328188724404">"kHz 48.0"</item>
+    <item msgid="7329816882213695083">"kHz 88.2"</item>
+    <item msgid="6967397666254430476">"kHz 96.0"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Tumia Uteuzi wa Mfumo (Chaguo-msingi)"</item>
+    <item msgid="5618929009984956469">"Biti 16 kwa kila sampuli"</item>
+    <item msgid="3412640499234627248">"Biti 24 kwa kila sampuli"</item>
+    <item msgid="121583001492929387">"Biti 32 kwa kila sampuli"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Tumia Uteuzi wa Mfumo (Chaguo-msingi)"</item>
+    <item msgid="4726688794884191540">"Biti 16 kwa kila sampuli"</item>
+    <item msgid="305344756485516870">"Biti 24 kwa kila sampuli"</item>
+    <item msgid="244568657919675099">"Biti 32 kwa kila sampuli"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Tumia Uteuzi wa Mfumo (Chaguo-msingi)"</item>
+    <item msgid="4106832974775067314">"Mono"</item>
+    <item msgid="5571632958424639155">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Tumia Uteuzi wa Mfumo (Chaguo-msingi)"</item>
+    <item msgid="8900559293912978337">"Mono"</item>
+    <item msgid="8883739882299884241">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Imarisha kwa ajili ya Ubora wa Sauti (990kbps/909kbps)"</item>
+    <item msgid="2921767058740704969">"Ubora wa Muunganisho na Sauti Umesawazishwa (660kbps/606kbps)"</item>
+    <item msgid="3682554248829489641">"Imarisha kwa ajili ya Ubora wa Muunganisho (330kbps/303kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Imarisha kwa ajili ya Ubora wa Sauti"</item>
+    <item msgid="4327143584633311908">"Ubora wa Muunganisho na Sauti Umesawazishwa"</item>
+    <item msgid="6155648878105378550">"Imarisha kwa ajili ya Ubora wa Muunganisho"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Imezimwa"</item>
     <item msgid="1593289376502312923">"K64"</item>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 1b2f876..9296e81 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Data ya kifaa cha mkononi inatumika kila wakati"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Zima sauti kamili"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Kodeki ya Sauti ya Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Chagua Kodeki ya Sauti ya Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Kiwango cha Sampuli ya Sauti ya Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Chagua Kodeki ya Sauti ya Bluetooth:\nKiwango cha Sampuli"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Biti za Sauti ya Bluetooth kwa Kila Sampuli"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Chagua Kodeki ya Sauti ya Bluetooth:\nBiti kwa Kila Sampuli"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Hali ya Mkondo wa Sauti ya Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Chagua Kodeki ya Sauti ya Bluetooth:\nHali ya Kituo"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Kodeki ya LDAC ya Sauti ya Bluetooth: Ubora wa Kucheza"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Chagua Kodeki ya LDAC ya Sauti ya Bluetooth:\nUbora wa Kucheza"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Kutiririsha: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Onyesha chaguo za cheti cha kuonyesha pasiwaya"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Ongeza hatua ya uwekaji kumbukumbu ya Wi-Fi, onyesha kwa kila SSID RSSI kwenye Kichukuzi cha Wi-Fi"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Ikiwashwa, Wifi itakabidhi kwa hima muunganisho wa data kwa mtandao wa Simu za Mkononi, mawimbi ya Wifi yanapokuwa hafifu"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Usaidizi na maoni"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menyu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Weka nenosiri ili urejeshe mipangilio ya kiwandani ikiwa katika hali ya onyesho."</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Inayofuata"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Nenosiri linahitajika"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index a94dd3a..790eb67 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"உதவி &amp; கருத்து"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"மெனு"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"டெமோ பயன்முறையில் ஆரம்பநிலை மீட்டமைவைச் செயல்படுத்த, கடவுச்சொல்லை உள்ளிடவும்"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"அடுத்து"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"கடவுச்சொல் தேவை"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index bee6402..44a16b1 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"DRM కంటెంట్‌కు మాత్రమే HDCP తనిఖీని ఉపయోగించండి"</item>
     <item msgid="45075631231212732">"ఎప్పటికీ HDCP తనిఖీని ఉపయోగించు"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"సిస్టమ్ ఎంపికను ఉపయోగించండి (డిఫాల్ట్)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"సిస్టమ్ ఎంపికను ఉపయోగించండి (డిఫాల్ట్)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"సిస్టమ్ ఎంపికను ఉపయోగించండి (డిఫాల్ట్)"</item>
+    <item msgid="8895532488906185219">"44.1 kHz"</item>
+    <item msgid="2909915718994807056">"48.0 kHz"</item>
+    <item msgid="3347287377354164611">"88.2 kHz"</item>
+    <item msgid="1234212100239985373">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"సిస్టమ్ ఎంపికను ఉపయోగించండి (డిఫాల్ట్)"</item>
+    <item msgid="4482862757811638365">"44.1 kHz"</item>
+    <item msgid="354495328188724404">"48.0 kHz"</item>
+    <item msgid="7329816882213695083">"88.2 kHz"</item>
+    <item msgid="6967397666254430476">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"సిస్టమ్ ఎంపికను ఉపయోగించండి (డిఫాల్ట్)"</item>
+    <item msgid="5618929009984956469">"16 బిట్‌లు/నమూనా"</item>
+    <item msgid="3412640499234627248">"24 బిట్‌లు/నమూనా"</item>
+    <item msgid="121583001492929387">"32 బిట్‌లు/నమూనా"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"సిస్టమ్ ఎంపికను ఉపయోగించండి (డిఫాల్ట్)"</item>
+    <item msgid="4726688794884191540">"16 బిట్‌లు/నమూనా"</item>
+    <item msgid="305344756485516870">"24 బిట్‌లు/నమూనా"</item>
+    <item msgid="244568657919675099">"32 బిట్‌లు/నమూనా"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"సిస్టమ్ ఎంపికను ఉపయోగించండి (డిఫాల్ట్)"</item>
+    <item msgid="4106832974775067314">"మోనో"</item>
+    <item msgid="5571632958424639155">"స్టీరియో"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"సిస్టమ్ ఎంపికను ఉపయోగించండి (డిఫాల్ట్)"</item>
+    <item msgid="8900559293912978337">"మోనో"</item>
+    <item msgid="8883739882299884241">"స్టీరియో"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"ఆడియో నాణ్యత కోసం అనుకూలీకరించండి (990kbps/909kbps)"</item>
+    <item msgid="2921767058740704969">"సమతుల్య ఆడియో మరియు కనెక్షన్ నాణ్యత (660kbps/606kbps)"</item>
+    <item msgid="3682554248829489641">"కనెక్షన్ నాణ్యత కోసం అనుకూలీకరించండి (330kbps/303kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"ఆడియో నాణ్యత కోసం అనుకూలీకరించండి"</item>
+    <item msgid="4327143584633311908">"సమతుల్య ఆడియో మరియు కనెక్షన్ నాణ్యత"</item>
+    <item msgid="6155648878105378550">"కనెక్షన్ నాణ్యత కోసం అనుకూలీకరించండి"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"ఆఫ్"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index d96e412..8379dd8 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"ఎల్లప్పుడూ సెల్యులార్ డేటాను సక్రియంగా ఉంచు"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"సంపూర్ణ వాల్యూమ్‌‍ను నిలిపివేయి"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"బ్లూటూత్ ఆడియో కోడెక్"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"బ్లూటూత్ ఆడియో కోడెక్‌ని ఎంచుకోండి"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"బ్లూటూత్ ఆడియో నమూనా రేట్"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"బ్లూటూత్ ఆడియో కోడెక్‌ని ఎంచుకోండి:\nనమూనా రేటు"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"ఒక్కో నమూనాకు బ్లూటూత్ ఆడియో బిట్‌లు"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"బ్లూటూత్ ఆడియో కోడెక్‌ని ఎంచుకోండి:\nఒక్కో నమూనాలో బిట్‌లు"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"బ్లూటూత్ ఆడియో ఛానెల్ మోడ్"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"బ్లూటూత్ ఆడియో కోడెక్‌ని ఎంచుకోండి:\nఛానెల్ మోడ్"</string>
+    <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_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ఎంపికలో SSID RSSI ప్రకారం చూపబడే Wi‑Fi లాగింగ్ స్థాయిని పెంచండి"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"ప్రారంభించబడినప్పుడు, Wi‑Fi సిగ్నల్ బలహీనంగా ఉంటే డేటా కనెక్షన్‌ను సెల్యులార్‌కి మార్చేలా Wi‑Fiపై మరింత తీవ్ర ఒత్తిడి కలుగుతుంది"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"సహాయం &amp; అభిప్రాయం"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"మెను"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"డెమో మోడ్‌లో ఫ్యాక్టరీ రీసెట్‌ను నిర్వహించడానికి పాస్‌వర్డ్‌ను నమోదు చేయండి"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"తదుపరి"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"పాస్‌వర్డ్ అవసరం"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml
index 690ce0c..519a439 100644
--- a/packages/SettingsLib/res/values-th/arrays.xml
+++ b/packages/SettingsLib/res/values-th/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"ใช้การตรวจสอบ HDCP สำหรับเนื้อหา DRM เท่านั้น"</item>
     <item msgid="45075631231212732">"ใช้การตรวจสอบ HDCP เสมอ"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"ใช้การเลือกระบบ (ค่าเริ่มต้น)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"ใช้การเลือกระบบ (ค่าเริ่มต้น)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"ใช้การเลือกระบบ (ค่าเริ่มต้น)"</item>
+    <item msgid="8895532488906185219">"44.1 kHz"</item>
+    <item msgid="2909915718994807056">"48.0 kHz"</item>
+    <item msgid="3347287377354164611">"88.2 kHz"</item>
+    <item msgid="1234212100239985373">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"ใช้การเลือกระบบ (ค่าเริ่มต้น)"</item>
+    <item msgid="4482862757811638365">"44.1 kHz"</item>
+    <item msgid="354495328188724404">"48.0 kHz"</item>
+    <item msgid="7329816882213695083">"88.2 kHz"</item>
+    <item msgid="6967397666254430476">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"ใช้การเลือกระบบ (ค่าเริ่มต้น)"</item>
+    <item msgid="5618929009984956469">"16 บิต/ตัวอย่าง"</item>
+    <item msgid="3412640499234627248">"24 บิต/ตัวอย่าง"</item>
+    <item msgid="121583001492929387">"32 บิต/ตัวอย่าง"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"ใช้การเลือกระบบ (ค่าเริ่มต้น)"</item>
+    <item msgid="4726688794884191540">"16 บิต/ตัวอย่าง"</item>
+    <item msgid="305344756485516870">"24 บิต/ตัวอย่าง"</item>
+    <item msgid="244568657919675099">"32 บิต/ตัวอย่าง"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"ใช้การเลือกระบบ (ค่าเริ่มต้น)"</item>
+    <item msgid="4106832974775067314">"โมโน"</item>
+    <item msgid="5571632958424639155">"สเตอริโอ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"ใช้การเลือกระบบ (ค่าเริ่มต้น)"</item>
+    <item msgid="8900559293912978337">"โมโน"</item>
+    <item msgid="8883739882299884241">"สเตอริโอ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"เพิ่มประสิทธิภาพสำหรับคุณภาพเสียง (990 kbps/909 kbps)"</item>
+    <item msgid="2921767058740704969">"คุณภาพเสียงและการเชื่อมต่อที่สมดุล (660 kbps/606 kbps)"</item>
+    <item msgid="3682554248829489641">"เพิ่มประสิทธิภาพสำหรับคุณภาพการเชื่อมต่อ (330 kbps/303 kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"เพิ่มประสิทธิภาพสำหรับคุณภาพเสียง"</item>
+    <item msgid="4327143584633311908">"คุณภาพเสียงและการเชื่อมต่อที่สมดุล"</item>
+    <item msgid="6155648878105378550">"เพิ่มประสิทธิภาพสำหรับคุณภาพการเชื่อมต่อ"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"ปิด"</item>
     <item msgid="1593289376502312923">"64 K"</item>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 3d8af85..8f9bd86 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"เปิดใช้ข้อมูลมือถือเสมอ"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"ปิดใช้การควบคุมระดับเสียงของอุปกรณ์อื่น"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"ตัวแปลงรหัสเสียงบลูทูธ"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"เลือกตัวแปลงรหัสเสียงบลูทูธ"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"อัตราตัวอย่างเสียงบลูทูธ"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"เลือกตัวแปลงรหัสเสียงบลูทูธ:\nอัตราการสุ่มตัวอย่าง"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"บิตต่อตัวอย่างของเสียงบลูทูธ"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"เลือกตัวแปลงรหัสเสียงบลูทูธ:\nบิตต่อตัวอย่าง"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"โหมดช่องสัญญาณเสียงบลูทูธ"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"เลือกตัวแปลงรหัสเสียงบลูทูธ:\nโหมดช่องสัญญาณ"</string>
+    <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_verbose_logging_summary" msgid="6615071616111731958">"เพิ่มระดับการบันทึก Wi‑Fi แสดงต่อ SSID RSSI ในตัวเลือก Wi‑Fi"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"เมื่อเปิดใช้แล้ว Wi-Fi จะส่งผ่านการเชื่อมต่อข้อมูลไปยังเครือข่ายมือถือในทันทีที่พบสัญญาณ Wi-Fi อ่อน"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"ความช่วยเหลือและความคิดเห็น"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"เมนู"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"ป้อนรหัสผ่านเพื่อรีเซ็ตค่าในโหมดสาธิต"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"ถัดไป"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"ต้องป้อนรหัสผ่าน"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index a7ccc2a..682ee0ed 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Tulong at feedback"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Ilagay ang password upang mag-factory reset sa demo mode"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Susunod"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Kinakailangan ang password"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index a452481..3101b2c 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Yardım ve geri bildirim"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menü"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Demo modunda sıfırlamak için şifreyi girin"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Sonraki"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Şifre gerekli"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index b67c7c9..5e241f5 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Довідка й відгуки"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Меню"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Введіть пароль, щоб скинути налаштування в демо-режимі"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Далі"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Потрібен пароль"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml
index d970f19..d55bd2b 100644
--- a/packages/SettingsLib/res/values-ur/arrays.xml
+++ b/packages/SettingsLib/res/values-ur/arrays.xml
@@ -58,22 +58,66 @@
     <item msgid="3878793616631049349">"‏HDCP چیکنگ صرف DRM مواد کیلئے استعمال کریں"</item>
     <item msgid="45075631231212732">"‏ہمیشہ HDCP چیکنگ استعمال کریں"</item>
   </string-array>
-    <!-- no translation found for bluetooth_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
+    <item msgid="8895532488906185219">"44.1 kHz"</item>
+    <item msgid="2909915718994807056">"48.0 kHz"</item>
+    <item msgid="3347287377354164611">"88.2 kHz"</item>
+    <item msgid="1234212100239985373">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
+    <item msgid="4482862757811638365">"44.1 kHz"</item>
+    <item msgid="354495328188724404">"48.0 kHz"</item>
+    <item msgid="7329816882213695083">"88.2 kHz"</item>
+    <item msgid="6967397666254430476">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
+    <item msgid="5618929009984956469">"16 بٹس/نمونہ"</item>
+    <item msgid="3412640499234627248">"24 بٹس/نمونہ"</item>
+    <item msgid="121583001492929387">"32 بٹس/نمونہ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
+    <item msgid="4726688794884191540">"16 بٹس/نمونہ"</item>
+    <item msgid="305344756485516870">"24 بٹس/نمونہ"</item>
+    <item msgid="244568657919675099">"32 بٹس/نمونہ"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
+    <item msgid="4106832974775067314">"مونو"</item>
+    <item msgid="5571632958424639155">"اسٹیریو"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"سسٹم انتخاب کا استعمال کریں (ڈیفالٹ)"</item>
+    <item msgid="8900559293912978337">"مونو"</item>
+    <item msgid="8883739882299884241">"اسٹیریو"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"‏آڈیو کے معیار کے لیے بہتر بنائیں (990kbps/909kbps)"</item>
+    <item msgid="2921767058740704969">"‏متوازن آڈیو اور کنکشن کا معیار (660kbps/606kbps)"</item>
+    <item msgid="3682554248829489641">"‏کنکشن کے معیار کے لیے بہتر بنائیں (330kbps/303kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"آڈیو کے معیار کے لیے بہتر بنائیں"</item>
+    <item msgid="4327143584633311908">"متوازن آڈیو اور کنکشن کا معیار"</item>
+    <item msgid="6155648878105378550">"کنکشن کے معیار کے لیے بہتر بنائیں"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"آف"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index d4ad6b9..d4c97cd 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"سیلولر ڈیٹا کو ہمیشہ فعال رکھیں"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"مطلق والیوم کو غیر فعال کریں"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"بلوٹوتھ آڈیو کوڈیک"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"بلوٹوتھ آڈیو کوڈیک منتخب کریں"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"بلوٹوتھ آڈیو کے نمونے کی شرح"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"بلوٹوتھ آڈیو کوڈیک منتخب کریں:\nنمونے کی شرح"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"بلوٹوتھ آڈیو بٹس فی نمونہ"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"بلوٹوتھ آڈیو کوڈیک منتخب کریں:\nبٹس فی نمونہ"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"بلوٹوتھ آڈیو چینل موڈ"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"بلوٹوتھ آڈیو کوڈیک منتخب کریں:\nچینل موڈ"</string>
+    <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_verbose_logging_summary" msgid="6615071616111731958">"‏Wi‑Fi لاگنگ لیول میں اضافہ کریں، Wi‑Fi منتخب کنندہ میں فی SSID RSSI دکھائیں"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"‏فعال ہونے پر، جب Wi‑Fi سگنل کمزور ہوگا تو Wi‑Fi سیلولر پر ڈیٹا کنکشن بھیجنے کیلئے مزید جارحانہ کاروائی کرے گا۔"</string>
@@ -360,4 +353,10 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"مدد اور تاثرات"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"مینو"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <!-- no translation found for retail_demo_reset_message (118771671364131297) -->
+    <skip />
+    <!-- no translation found for retail_demo_reset_next (8356731459226304963) -->
+    <skip />
+    <!-- no translation found for retail_demo_reset_title (696589204029930100) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml
index f784021..f222d1f 100644
--- a/packages/SettingsLib/res/values-uz/arrays.xml
+++ b/packages/SettingsLib/res/values-uz/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Tizim tanlovi (birlamchi)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Tizim tanlovi (birlamchi)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Tizim tanlovi (birlamchi)"</item>
+    <item msgid="8895532488906185219">"44.1 kGs"</item>
+    <item msgid="2909915718994807056">"48.0 kGs"</item>
+    <item msgid="3347287377354164611">"88.2 kGs"</item>
+    <item msgid="1234212100239985373">"96.0 kGs"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Tizim tanlovi (birlamchi)"</item>
+    <item msgid="4482862757811638365">"44.1 kGs"</item>
+    <item msgid="354495328188724404">"48.0 kGs"</item>
+    <item msgid="7329816882213695083">"88.2 kGs"</item>
+    <item msgid="6967397666254430476">"96.0 kGs"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Tizim tanlovi (birlamchi)"</item>
+    <item msgid="5618929009984956469">"16 bit/namuna"</item>
+    <item msgid="3412640499234627248">"24 bit/namuna"</item>
+    <item msgid="121583001492929387">"32 bit/namuna"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Tizim tanlovi (birlamchi)"</item>
+    <item msgid="4726688794884191540">"16 bit/namuna"</item>
+    <item msgid="305344756485516870">"24 bit/namuna"</item>
+    <item msgid="244568657919675099">"32 bit/namuna"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Tizim tanlovi (birlamchi)"</item>
+    <item msgid="4106832974775067314">"Mono"</item>
+    <item msgid="5571632958424639155">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Tizim tanlovi (birlamchi)"</item>
+    <item msgid="8900559293912978337">"Mono"</item>
+    <item msgid="8883739882299884241">"Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Audio sifati uchun moslashtirish (990/909 kbit/s)"</item>
+    <item msgid="2921767058740704969">"Audio sifati balansi va ulanish tezligi (660/606 kbit/s)"</item>
+    <item msgid="3682554248829489641">"Ulanish sifati uchun moslashtirish (330/303 kbit/s)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Audio sifati uchun moslashtirish"</item>
+    <item msgid="4327143584633311908">"Audio sifati balansi va ulanish tezligi"</item>
+    <item msgid="6155648878105378550">"Ulanish sifati uchun moslashtirish"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"O‘chiq"</item>
     <item msgid="1593289376502312923">"64 KB"</item>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index f50f36b..b5460c2 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Mobil internet o‘chirilmasin"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Ovoz balangligining mutlaq darajasini o‘chirib qo‘yish"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Bluetooth audio kodeki"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Bluetooth orqali uzatish uchun audiokodek"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Bluetooth audio namunasi chastotasi"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Bluetooth orqali uzatish uchun audiokodek:\nnamuna chastotasi"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Bluetooth audio namunasidagi bitlar soni"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Bluetooth orqali uzatish uchun audiokodek:\nnamunadagi bitlar soni"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Bluetooth audio kanali rejimi"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Bluetooth orqali uzatish uchun audiokodek:\nkanal rejimi"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"LDAC audiokodeki bilan ijro etish sifati (Bluetooth orqali)"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"LDAC audiokodeki:\nijro sifati"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Translatsiya: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Simsiz monitorlarni sertifikatlash parametrini ko‘rsatish"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi ulanishini tanlashda har bir SSID uchun jurnalda ko‘rsatilsin"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Agar ushbu funksiya yoqilsa, Wi-Fi signali past bo‘lganda internetga ulanish majburiy ravishda mobil internetga o‘tkaziladi."</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Yordam va fikr-mulohaza"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menyu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Demo rejimda zavod holatiga qaytarish uchun parolni kiriting"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Keyingisi"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Parolni kiritish zarur"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-vi/arrays.xml b/packages/SettingsLib/res/values-vi/arrays.xml
index 21bbf0a..7b2368f 100644
--- a/packages/SettingsLib/res/values-vi/arrays.xml
+++ b/packages/SettingsLib/res/values-vi/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <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>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Sử dụng lựa chọn hệ thống (Mặc định)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Sử dụng lựa chọn hệ thống (Mặc định)"</item>
+    <item msgid="8895532488906185219">"44,1 kHz"</item>
+    <item msgid="2909915718994807056">"48,0 kHz"</item>
+    <item msgid="3347287377354164611">"88,2 kHz"</item>
+    <item msgid="1234212100239985373">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Sử dụng lựa chọn hệ thống (Mặc định)"</item>
+    <item msgid="4482862757811638365">"44,1 kHz"</item>
+    <item msgid="354495328188724404">"48,0 kHz"</item>
+    <item msgid="7329816882213695083">"88,2 kHz"</item>
+    <item msgid="6967397666254430476">"96,0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Sử dụng lựa chọn hệ thống (Mặc định)"</item>
+    <item msgid="5618929009984956469">"16 bit/mẫu"</item>
+    <item msgid="3412640499234627248">"24 bit/mẫu"</item>
+    <item msgid="121583001492929387">"32 bit/mẫu"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Sử dụng lựa chọn hệ thống (Mặc định)"</item>
+    <item msgid="4726688794884191540">"16 bit/mẫu"</item>
+    <item msgid="305344756485516870">"24 bit/mẫu"</item>
+    <item msgid="244568657919675099">"32 bit/mẫu"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Sử dụng lựa chọn hệ thống (Mặc định)"</item>
+    <item msgid="4106832974775067314">"Đơn âm"</item>
+    <item msgid="5571632958424639155">"Âm thanh nổi"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Sử dụng lựa chọn hệ thống (Mặc định)"</item>
+    <item msgid="8900559293912978337">"Đơn âm"</item>
+    <item msgid="8883739882299884241">"Âm thanh nổi"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Tối ưu hóa chất lượng âm thanh (990kbps/909kbps)"</item>
+    <item msgid="2921767058740704969">"Chất lượng kết nối và âm thanh cân bằng (660kbps/606kbps)"</item>
+    <item msgid="3682554248829489641">"Tối ưu hóa chất lượng kết nối (330kbps/303kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Tối ưu hóa chất lượng âm thanh"</item>
+    <item msgid="4327143584633311908">"Chất lượng kết nối và âm thanh cân bằng"</item>
+    <item msgid="6155648878105378550">"Tối ưu hóa chất lượng kết nối"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Tắt"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 85be70e..ff9a557 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Dữ liệu di động luôn hoạt động"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Vô hiệu hóa âm lượng tuyệt đối"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"Codec âm thanh Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Chọn Codec âm thanh Bluetooth"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Tốc độ lấy mẫu âm thanh Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Chọn Codec âm thanh Bluetooth:\nTốc độ lấy mẫu"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Số bit âm thanh Bluetooth mỗi mẫu"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Chọn Codec âm thanh Bluetooth:\nSố bit trên mẫu"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Chế độ kênh âm thanh Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Chọn Codec âm thanh Bluetooth:\nChế độ kênh"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"Codec LDAC âm thanh Bluetooth: Chất lượng phát lại"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Chọn Codec LDAC âm thanh Bluetooth:\nChất lượng phát lại"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Truyền trực tuyến: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Hiển thị tùy chọn chứng nhận hiển thị không dây"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Tăng mức ghi nhật ký Wi‑Fi, hiển thị mỗi SSID RSSI trong bộ chọn Wi‑Fi"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Khi được bật, Wi‑Fi sẽ tích cực hơn trong việc chuyển vùng kết nối dữ liệu sang mạng di động khi tín hiệu Wi‑Fi yếu"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Trợ giúp và phản hồi"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Menu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Nhập mật khẩu để tiến hành khôi phục cài đặt gốc ở chế độ trình diễn"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Tiếp theo"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Yêu cầu mật khẩu"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 3ab17fb..4c47ace 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -360,4 +360,10 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"帮助和反馈"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"菜单"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <!-- no translation found for retail_demo_reset_message (118771671364131297) -->
+    <skip />
+    <!-- no translation found for retail_demo_reset_next (8356731459226304963) -->
+    <skip />
+    <!-- no translation found for retail_demo_reset_title (696589204029930100) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 79fc760..3d8b673 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"說明和意見反映"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"選單"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"輸入密碼即可在示範模式下重設原廠設定"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"下一步"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"請輸入密碼"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 2a32252..ad3b83a 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -360,4 +360,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"說明與意見回饋"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"選單"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"如要在示範模式中恢復原廠設定,請輸入密碼"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"下一步"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"請輸入密碼"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values-zu/arrays.xml b/packages/SettingsLib/res/values-zu/arrays.xml
index 04e7614..50597f3 100644
--- a/packages/SettingsLib/res/values-zu/arrays.xml
+++ b/packages/SettingsLib/res/values-zu/arrays.xml
@@ -58,22 +58,66 @@
     <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_a2dp_codec_titles:0 (7065842274271279580) -->
-    <!-- no translation found for bluetooth_a2dp_codec_titles:3 (500463122137421129) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:0 (5062108632402595000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_summaries:3 (3093550793512117000) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_titles:0 (3093023430402746802) -->
-    <!-- no translation found for bluetooth_a2dp_codec_sample_rate_summaries:0 (3214516120190965356) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_titles:0 (2684127272582591429) -->
-    <!-- no translation found for bluetooth_a2dp_codec_bits_per_sample_summaries:0 (1081159789834584363) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_titles:0 (5226878858503393706) -->
-    <!-- no translation found for bluetooth_a2dp_codec_channel_mode_summaries:0 (4118561796005528173) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:0 (3411577996960199959) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:1 (2921767058740704969) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_titles:2 (3682554248829489641) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:0 (7668834469173465015) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:1 (4327143584633311908) -->
-    <!-- no translation found for bluetooth_a2dp_codec_ldac_playback_quality_summaries:2 (6155648878105378550) -->
+  <string-array name="bluetooth_a2dp_codec_titles">
+    <item msgid="7065842274271279580">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item>
+    <item msgid="7539690996561263909">"SBC"</item>
+    <item msgid="4260844283202960798">"aptX"</item>
+    <item msgid="500463122137421129">"aptX HD"</item>
+    <item msgid="2301339338870319651">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_summaries">
+    <item msgid="5062108632402595000">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item>
+    <item msgid="6898329690939802290">"SBC"</item>
+    <item msgid="1190434429082395888">"aptX"</item>
+    <item msgid="3093550793512117000">"aptX HD"</item>
+    <item msgid="508106435710925399">"LDAC"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
+    <item msgid="3093023430402746802">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item>
+    <item msgid="8895532488906185219">"44.1 kHz"</item>
+    <item msgid="2909915718994807056">"48.0 kHz"</item>
+    <item msgid="3347287377354164611">"88.2 kHz"</item>
+    <item msgid="1234212100239985373">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
+    <item msgid="3214516120190965356">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item>
+    <item msgid="4482862757811638365">"44.1 kHz"</item>
+    <item msgid="354495328188724404">"48.0 kHz"</item>
+    <item msgid="7329816882213695083">"88.2 kHz"</item>
+    <item msgid="6967397666254430476">"96.0 kHz"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
+    <item msgid="2684127272582591429">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item>
+    <item msgid="5618929009984956469">"16 bits/isampula"</item>
+    <item msgid="3412640499234627248">"24 bits/isampula"</item>
+    <item msgid="121583001492929387">"32 bits/isampula"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
+    <item msgid="1081159789834584363">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item>
+    <item msgid="4726688794884191540">"16 bits/isampula"</item>
+    <item msgid="305344756485516870">"24 bits/isampula"</item>
+    <item msgid="244568657919675099">"32 bits/isampula"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
+    <item msgid="5226878858503393706">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item>
+    <item msgid="4106832974775067314">"Okukodwa"</item>
+    <item msgid="5571632958424639155">"I-Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
+    <item msgid="4118561796005528173">"Sebenzisa ukukhetha kwesistimu (Okuzenzakalelayo)"</item>
+    <item msgid="8900559293912978337">"Okukodwa"</item>
+    <item msgid="8883739882299884241">"I-Stereo"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
+    <item msgid="3411577996960199959">"Thuthukisela ikhwalithi yomsindo (990kbps/909kbps)"</item>
+    <item msgid="2921767058740704969">"Umsindo obhalansile nekhwalithi yoxhumo (660kbps/606kbps)"</item>
+    <item msgid="3682554248829489641">"Thuthukisela ikhwalithi yoxhumo (330kbps/303kbps)"</item>
+  </string-array>
+  <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries">
+    <item msgid="7668834469173465015">"Thuthukisela ikhwalithi yomsindo"</item>
+    <item msgid="4327143584633311908">"Umsindo obhalansile nekhwalithi yoxhumo"</item>
+    <item msgid="6155648878105378550">"Thuthukisela ikhwalithi yoxhumo"</item>
+  </string-array>
   <string-array name="select_logd_size_titles">
     <item msgid="8665206199209698501">"Valiwe"</item>
     <item msgid="1593289376502312923">"64K"</item>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 143d4d1..9f7e72e 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -171,23 +171,16 @@
     <string name="mobile_data_always_on" msgid="7745605759775320362">"Idatha yeselula ihlala isebenza"</string>
     <string name="bluetooth_disable_absolute_volume" msgid="2660673801947898809">"Khubaza ivolumu ngokuphelele"</string>
     <string name="bluetooth_select_a2dp_codec_type" msgid="90597356942154882">"I-Bluetooth Audio Codec"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_type_dialog_title (4558347981670553665) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_type_dialog_title" msgid="4558347981670553665">"Khetha i-Bluetooth Audio Codec"</string>
     <string name="bluetooth_select_a2dp_codec_sample_rate" msgid="4788245703824623062">"Isilinganiso sesampula yomsindo we-Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_sample_rate_dialog_title (5628790207448471613) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_sample_rate_dialog_title" msgid="5628790207448471613">"Khetha i-Bluetooth Audio Codec:\nIsilinganiso sesampula"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="2099645202720164141">"Ama-Bits omsindo we-Bluetooth ngesampula ngayinye"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_bits_per_sample_dialog_title (4546131401358681321) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4546131401358681321">"Khetha i-Bluetooth Audio Codec:\nBits ngesampuli"</string>
     <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="884855779449390540">"Imodi yesiteshi somsindo we-Bluetooth"</string>
-    <!-- no translation found for bluetooth_select_a2dp_codec_channel_mode_dialog_title (9133545781346216071) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality (3619694372407843405) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title (3181967377574368400) -->
-    <skip />
-    <!-- no translation found for bluetooth_select_a2dp_codec_streaming_label (5347862512596240506) -->
-    <skip />
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="9133545781346216071">"Khetha i-Bluetooth Audio Codec:\nImodi yesiteshi"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3619694372407843405">"I-Bluetooth Audio LDAC Codec: Ikhwalithi yokudlala"</string>
+    <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="3181967377574368400">"Khetha i-Bluetooth Audio LDAC Codec:\nIkhwalithi yokudlala"</string>
+    <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="5347862512596240506">"Ukusakaza: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"Bonisa izinketho zokunikeza isitifiketi ukubukeka okungenantambo"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"khuphula izinga lokungena le-Wi-Fi, bonisa nge-SSID RSSI engayodwana kusikhethi se-Wi-Fi"</string>
     <string name="wifi_aggressive_handover_summary" msgid="6328455667642570371">"Uma inikwe amandla, i-Wi-Fi izoba namandla kakhulu ekunikezeleni ukuxhumeka kwedatha kuselula, uma isiginali ye-Wi-Fi iphansi"</string>
@@ -360,4 +353,7 @@
     <string name="help_feedback_label" msgid="6815040660801785649">"Usizo nempendulo"</string>
     <string name="content_description_menu_button" msgid="8182594799812351266">"Imenyu"</string>
     <string name="time_zone_gmt" msgid="2587097992671450782">"I-GMT"</string>
+    <string name="retail_demo_reset_message" msgid="118771671364131297">"Faka iphasiwedi ukuze wenze ukusetha kwefekthri kumodi yedemo"</string>
+    <string name="retail_demo_reset_next" msgid="8356731459226304963">"Okulandelayo"</string>
+    <string name="retail_demo_reset_title" msgid="696589204029930100">"Iphasiwedi iyadingeka"</string>
 </resources>
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index cfb990e..7bbca5e 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -103,10 +103,11 @@
 
     <!-- Bluetooth settings -->
 
-    <!-- Titles for Bluetooth Audio Codec selection preference. [CHAR LIMIT=40] -->
+    <!-- Titles for Bluetooth Audio Codec selection preference. [CHAR LIMIT=50] -->
     <string-array name="bluetooth_a2dp_codec_titles">
         <item>Use System Selection (Default)</item>
         <item>SBC</item>
+        <item>AAC</item>
         <item>aptX</item>
         <item>aptX HD</item>
         <item>LDAC</item>
@@ -119,18 +120,20 @@
         <item>1</item>
         <item>2</item>
         <item>3</item>
+        <item>4</item>
     </string-array>
 
-    <!-- Summaries for Bluetooth Audio Codec selection preference. [CHAR LIMIT=40]-->
+    <!-- Summaries for Bluetooth Audio Codec selection preference. [CHAR LIMIT=50]-->
     <string-array name="bluetooth_a2dp_codec_summaries" >
         <item>Use System Selection (Default)</item>
         <item>SBC</item>
+        <item>AAC</item>
         <item>aptX</item>
         <item>aptX HD</item>
         <item>LDAC</item>
     </string-array>
 
-    <!-- Titles for Bluetooth Audio Codec Sample Rate selection preference. [CHAR LIMIT=40] -->
+    <!-- Titles for Bluetooth Audio Codec Sample Rate selection preference. [CHAR LIMIT=50] -->
     <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
         <item>Use System Selection (Default)</item>
         <item>44.1 kHz</item>
@@ -148,7 +151,7 @@
         <item>8</item>
     </string-array>
 
-    <!-- Summaries for Bluetooth Audio Codec Sample Rate selection preference. [CHAR LIMIT=40]-->
+    <!-- Summaries for Bluetooth Audio Codec Sample Rate selection preference. [CHAR LIMIT=50]-->
     <string-array name="bluetooth_a2dp_codec_sample_rate_summaries" >
         <item>Use System Selection (Default)</item>
         <item>44.1 kHz</item>
@@ -157,7 +160,7 @@
         <item>96.0 kHz</item>
     </string-array>
 
-    <!-- Titles for Bluetooth Audio Codec Bits Per Sample selection preference. [CHAR LIMIT=40] -->
+    <!-- Titles for Bluetooth Audio Codec Bits Per Sample selection preference. [CHAR LIMIT=50] -->
     <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
         <item>Use System Selection (Default)</item>
         <item>16 bits/sample</item>
@@ -173,7 +176,7 @@
         <item>4</item>
     </string-array>
 
-    <!-- Summaries for Bluetooth Audio Codec Bits Per Sample selection preference. [CHAR LIMIT=40]-->
+    <!-- Summaries for Bluetooth Audio Codec Bits Per Sample selection preference. [CHAR LIMIT=50]-->
     <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries" >
         <item>Use System Selection (Default)</item>
         <item>16 bits/sample</item>
@@ -181,7 +184,7 @@
         <item>32 bits/sample</item>
     </string-array>
 
-    <!-- Titles for Bluetooth Audio Codec Channel Mode selection preference. [CHAR LIMIT=40] -->
+    <!-- Titles for Bluetooth Audio Codec Channel Mode selection preference. [CHAR LIMIT=50] -->
     <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
         <item>Use System Selection (Default)</item>
         <item>Mono</item>
@@ -195,7 +198,7 @@
         <item>2</item>
     </string-array>
 
-    <!-- Summaries for Bluetooth Audio Codec Channel Mode selection preference. [CHAR LIMIT=40]-->
+    <!-- Summaries for Bluetooth Audio Codec Channel Mode selection preference. [CHAR LIMIT=50]-->
     <string-array name="bluetooth_a2dp_codec_channel_mode_summaries" >
         <item>Use System Selection (Default)</item>
         <item>Mono</item>
@@ -204,9 +207,9 @@
 
     <!-- Titles for Bluetooth Audio Codec LDAC Playback Quality selection preference. [CHAR LIMIT=70] -->
     <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles">
-        <item>Optimize for Audio Quality (990kbps/909kbps)</item>
+        <item>Optimized for Audio Quality (990kbps/909kbps)</item>
         <item>Balanced Audio And Connection Quality (660kbps/606kbps)</item>
-        <item>Optimize for Connection Quality (330kbps/303kbps)</item>
+        <item>Optimized for Connection Quality (330kbps/303kbps)</item>
     </string-array>
 
     <!-- Values for Bluetooth Audio Codec LDAC Playback Quaility selection preference. -->
@@ -218,9 +221,9 @@
 
     <!-- Summaries for Bluetooth Audio Codec LDAC Playback Quality selection preference. [CHAR LIMIT=70]-->
     <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries" >
-        <item>Optimize for Audio Quality</item>
+        <item>Optimized for Audio Quality</item>
         <item>Balanced Audio And Connection Quality</item>
-        <item>Optimize for Connection Quality</item>
+        <item>Optimized for Connection Quality</item>
     </string-array>
 
     <!-- Titles for logd limit size selection preference. [CHAR LIMIT=14] -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java b/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java
index b037a3da..fc697ce 100644
--- a/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/HelpUtils.java
@@ -198,7 +198,7 @@
             intent.putExtra(feedbackIntentExtraKey, packageNameKey);
             intent.putExtra(feedbackIntentNameKey, packageNameValue);
         }
-        intent.putExtra(EXTRA_THEME, 1 /* Light, dark action bar */);
+        intent.putExtra(EXTRA_THEME, 0 /* Light theme */);
         TypedArray array = context.obtainStyledAttributes(new int[]{android.R.attr.colorPrimary});
         intent.putExtra(EXTRA_PRIMARY_COLOR, array.getColor(0, 0));
         array.recycle();
diff --git a/packages/SettingsLib/src/com/android/settingslib/TronUtils.java b/packages/SettingsLib/src/com/android/settingslib/TronUtils.java
new file mode 100644
index 0000000..1d9d03a
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/TronUtils.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib;
+
+import android.content.Context;
+import android.net.ScoredNetwork;
+
+import com.android.internal.logging.MetricsLogger;
+
+/** Utilites for Tron Logging. */
+public final class TronUtils {
+
+    private TronUtils() {};
+
+    public static void logWifiSettingsBadge(Context context, int badgeEnum) {
+        logNetworkBadgeMetric(context, "settings_wifibadging", badgeEnum);
+    }
+
+    /**
+     * Logs an occurrence of the given network badge to a Histogram.
+     *
+     * @param context Context
+     * @param histogram the Tron histogram name to write to
+     * @param badgeEnum the {@link ScoredNetwork.Badging} badge value
+     * @throws IllegalArgumentException if the given badge enum is not supported
+     */
+    private static void logNetworkBadgeMetric(
+            Context context, String histogram, int badgeEnum)
+            throws IllegalArgumentException {
+        int bucket;
+        switch (badgeEnum) {
+            case ScoredNetwork.BADGING_NONE:
+                bucket = 0;
+                break;
+            case ScoredNetwork.BADGING_SD:
+                bucket = 1;
+                break;
+            case ScoredNetwork.BADGING_HD:
+                bucket = 2;
+                break;
+            case ScoredNetwork.BADGING_4K:
+                bucket = 3;
+                break;
+            default:
+                throw new IllegalArgumentException("Unsupported badge enum: " + badgeEnum);
+        }
+
+        MetricsLogger.histogram(context, histogram, bucket);
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/accessibility/LinkAccessibilityHelper.java b/packages/SettingsLib/src/com/android/settingslib/accessibility/LinkAccessibilityHelper.java
new file mode 100644
index 0000000..74b0c6b
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/accessibility/LinkAccessibilityHelper.java
@@ -0,0 +1,235 @@
+/*
+ * 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.settingslib.accessibility;
+
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
+import android.support.v4.widget.ExploreByTouchHelper;
+import android.text.Layout;
+import android.text.Spanned;
+import android.text.style.ClickableSpan;
+import android.util.Log;
+import android.view.accessibility.AccessibilityEvent;
+import android.widget.TextView;
+
+import java.util.List;
+
+/**
+ * COPIED FROM SETUP WIZARD An accessibility delegate that allows {@link
+ * android.text.style.ClickableSpan} to be focused and clicked by accessibility services.
+ *
+ * <p>Sample usage:
+ *
+ * <pre>
+ * LinkAccessibilityHelper mAccessibilityHelper;
+ *
+ * private void init() {
+ *     mAccessibilityHelper = new LinkAccessibilityHelper(myTextView);
+ *     ViewCompat.setAccessibilityDelegate(myTextView, mLinkHelper);
+ * }
+ *
+ * {@literal @}Override
+ * protected boolean dispatchHoverEvent({@literal @}NonNull MotionEvent event) {
+ *     if (mAccessibilityHelper != null && mAccessibilityHelper.dispatchHoverEvent(event)) {
+ *         return true;
+ *     }
+ *     return super.dispatchHoverEvent(event);
+ * }
+ * </pre>
+ *
+ * @see android.support.v4.widget.ExploreByTouchHelper
+ */
+public class LinkAccessibilityHelper extends ExploreByTouchHelper {
+
+    private static final String TAG = "LinkAccessibilityHelper";
+
+    private final TextView mView;
+    private final Rect mTempRect = new Rect();
+
+    public LinkAccessibilityHelper(TextView view) {
+        super(view);
+        mView = view;
+    }
+
+    @Override
+    protected int getVirtualViewAt(float x, float y) {
+        final CharSequence text = mView.getText();
+        if (text instanceof Spanned) {
+            final Spanned spannedText = (Spanned) text;
+            final int offset = getOffsetForPosition(mView, x, y);
+            ClickableSpan[] linkSpans = spannedText.getSpans(offset, offset, ClickableSpan.class);
+            if (linkSpans.length == 1) {
+                ClickableSpan linkSpan = linkSpans[0];
+                return spannedText.getSpanStart(linkSpan);
+            }
+        }
+        return INVALID_ID;
+    }
+
+    @Override
+    protected void getVisibleVirtualViews(List<Integer> virtualViewIds) {
+        final CharSequence text = mView.getText();
+        if (text instanceof Spanned) {
+            final Spanned spannedText = (Spanned) text;
+            ClickableSpan[] linkSpans =
+                    spannedText.getSpans(0, spannedText.length(), ClickableSpan.class);
+            for (ClickableSpan span : linkSpans) {
+                virtualViewIds.add(spannedText.getSpanStart(span));
+            }
+        }
+    }
+
+    @Override
+    protected void onPopulateEventForVirtualView(int virtualViewId, AccessibilityEvent event) {
+        final ClickableSpan span = getSpanForOffset(virtualViewId);
+        if (span != null) {
+            event.setContentDescription(getTextForSpan(span));
+        } else {
+            Log.e(TAG, "LinkSpan is null for offset: " + virtualViewId);
+            event.setContentDescription(mView.getText());
+        }
+    }
+
+    @Override
+    protected void onPopulateNodeForVirtualView(
+            int virtualViewId, AccessibilityNodeInfoCompat info) {
+        final ClickableSpan span = getSpanForOffset(virtualViewId);
+        if (span != null) {
+            info.setContentDescription(getTextForSpan(span));
+        } else {
+            Log.e(TAG, "LinkSpan is null for offset: " + virtualViewId);
+            info.setContentDescription(mView.getText());
+        }
+        info.setFocusable(true);
+        info.setClickable(true);
+        getBoundsForSpan(span, mTempRect);
+        if (mTempRect.isEmpty()) {
+            Log.e(TAG, "LinkSpan bounds is empty for: " + virtualViewId);
+            mTempRect.set(0, 0, 1, 1);
+        }
+        info.setBoundsInParent(mTempRect);
+        info.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
+    }
+
+    @Override
+    protected boolean onPerformActionForVirtualView(
+            int virtualViewId, int action, Bundle arguments) {
+        if (action == AccessibilityNodeInfoCompat.ACTION_CLICK) {
+            ClickableSpan span = getSpanForOffset(virtualViewId);
+            if (span != null) {
+                span.onClick(mView);
+                return true;
+            } else {
+                Log.e(TAG, "LinkSpan is null for offset: " + virtualViewId);
+            }
+        }
+        return false;
+    }
+
+    private ClickableSpan getSpanForOffset(int offset) {
+        CharSequence text = mView.getText();
+        if (text instanceof Spanned) {
+            Spanned spannedText = (Spanned) text;
+            ClickableSpan[] spans = spannedText.getSpans(offset, offset, ClickableSpan.class);
+            if (spans.length == 1) {
+                return spans[0];
+            }
+        }
+        return null;
+    }
+
+    private CharSequence getTextForSpan(ClickableSpan span) {
+        CharSequence text = mView.getText();
+        if (text instanceof Spanned) {
+            Spanned spannedText = (Spanned) text;
+            return spannedText.subSequence(
+                    spannedText.getSpanStart(span), spannedText.getSpanEnd(span));
+        }
+        return text;
+    }
+
+    // Find the bounds of a span. If it spans multiple lines, it will only return the bounds for the
+    // section on the first line.
+    private Rect getBoundsForSpan(ClickableSpan span, Rect outRect) {
+        CharSequence text = mView.getText();
+        outRect.setEmpty();
+        if (text instanceof Spanned) {
+            final Layout layout = mView.getLayout();
+            if (layout != null) {
+                Spanned spannedText = (Spanned) text;
+                final int spanStart = spannedText.getSpanStart(span);
+                final int spanEnd = spannedText.getSpanEnd(span);
+                final float xStart = layout.getPrimaryHorizontal(spanStart);
+                final float xEnd = layout.getPrimaryHorizontal(spanEnd);
+                final int lineStart = layout.getLineForOffset(spanStart);
+                final int lineEnd = layout.getLineForOffset(spanEnd);
+                layout.getLineBounds(lineStart, outRect);
+                if (lineEnd == lineStart) {
+                    // If the span is on a single line, adjust both the left and right bounds
+                    // so outrect is exactly bounding the span.
+                    outRect.left = (int) Math.min(xStart, xEnd);
+                    outRect.right = (int) Math.max(xStart, xEnd);
+                } else {
+                    // If the span wraps across multiple lines, only use the first line (as returned
+                    // by layout.getLineBounds above), and adjust the "start" of outrect to where
+                    // the span starts, leaving the "end" of outrect at the end of the line.
+                    // ("start" being left for LTR, and right for RTL)
+                    if (layout.getParagraphDirection(lineStart) == Layout.DIR_RIGHT_TO_LEFT) {
+                        outRect.right = (int) xStart;
+                    } else {
+                        outRect.left = (int) xStart;
+                    }
+                }
+
+                // Offset for padding
+                outRect.offset(mView.getTotalPaddingLeft(), mView.getTotalPaddingTop());
+            }
+        }
+        return outRect;
+    }
+
+    // Compat implementation of TextView#getOffsetForPosition().
+
+    private static int getOffsetForPosition(TextView view, float x, float y) {
+        if (view.getLayout() == null) return -1;
+        final int line = getLineAtCoordinate(view, y);
+        return getOffsetAtCoordinate(view, line, x);
+    }
+
+    private static float convertToLocalHorizontalCoordinate(TextView view, float x) {
+        x -= view.getTotalPaddingLeft();
+        // Clamp the position to inside of the view.
+        x = Math.max(0.0f, x);
+        x = Math.min(view.getWidth() - view.getTotalPaddingRight() - 1, x);
+        x += view.getScrollX();
+        return x;
+    }
+
+    private static int getLineAtCoordinate(TextView view, float y) {
+        y -= view.getTotalPaddingTop();
+        // Clamp the position to inside of the view.
+        y = Math.max(0.0f, y);
+        y = Math.min(view.getHeight() - view.getTotalPaddingBottom() - 1, y);
+        y += view.getScrollY();
+        return view.getLayout().getLineForVertical((int) y);
+    }
+
+    private static int getOffsetAtCoordinate(TextView view, int line, float x) {
+        x = convertToLocalHorizontalCoordinate(view, x);
+        return view.getLayout().getOffsetForHorizontal(line, x);
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
index 115c622..2fb6843 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
@@ -135,6 +135,10 @@
         mAdapter.setDiscoverableTimeout(timeout);
     }
 
+    public long getDiscoveryEndMillis() {
+        return mAdapter.getDiscoveryEndMillis();
+    }
+
     public void setName(String name) {
         mAdapter.setName(name);
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/LinkTextView.java b/packages/SettingsLib/src/com/android/settingslib/widget/LinkTextView.java
new file mode 100644
index 0000000..da86536
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/widget/LinkTextView.java
@@ -0,0 +1,66 @@
+/*
+ * 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.settingslib.widget;
+
+import android.content.Context;
+import android.support.annotation.NonNull;
+import android.support.v4.view.ViewCompat;
+import android.text.Spanned;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ClickableSpan;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.TextView;
+import com.android.settingslib.accessibility.LinkAccessibilityHelper;
+/**
+ * Copied from setup wizard. This TextView performs two functions. The first is to make it so the
+ * link behaves properly and becomes clickable. The second is that it makes the link visible to
+ * accessibility services.
+ */
+public class LinkTextView extends TextView {
+
+    private LinkAccessibilityHelper mAccessibilityHelper;
+
+    public LinkTextView(Context context) {
+        this(context, null);
+    }
+
+    public LinkTextView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mAccessibilityHelper = new LinkAccessibilityHelper(this);
+        ViewCompat.setAccessibilityDelegate(this, mAccessibilityHelper);
+    }
+
+    @Override
+    public void setText(CharSequence text, BufferType type) {
+        super.setText(text, type);
+        if (text instanceof Spanned) {
+            final ClickableSpan[] spans =
+                    ((Spanned) text).getSpans(0, text.length(), ClickableSpan.class);
+            if (spans.length > 0) {
+                setMovementMethod(LinkMovementMethod.getInstance());
+            }
+        }
+    }
+
+    @Override
+    protected boolean dispatchHoverEvent(@NonNull MotionEvent event) {
+        if (mAccessibilityHelper.dispatchHoverEvent(event)) {
+            return true;
+        }
+        return super.dispatchHoverEvent(event);
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index 8ebea61..703bc17 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -34,7 +34,9 @@
 import android.util.SparseArray;
 import android.widget.ImageView;
 import android.widget.TextView;
+
 import com.android.settingslib.R;
+import com.android.settingslib.TronUtils;
 import com.android.settingslib.Utils;
 
 public class AccessPointPreference extends Preference {
@@ -184,7 +186,8 @@
         if (level == -1) {
             safeSetDefaultIcon();
         } else {
-           if (mWifiBadge != ScoredNetwork.BADGING_NONE) {
+            TronUtils.logWifiSettingsBadge(context, mWifiBadge);
+            if (mWifiBadge != ScoredNetwork.BADGING_NONE) {
                 // TODO(sghuman): Refactor this to reuse drawable to save memory and add to a
                 // special subclass of AccessPointPreference
                 LayerDrawable drawable = Utils.getBadgedWifiIcon(context, level, mWifiBadge);
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 799f388..c617994 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -16,9 +16,11 @@
 package com.android.settingslib.wifi;
 
 import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
 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;
@@ -38,6 +40,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.provider.Settings;
 import android.support.annotation.WorkerThread;
 import android.util.ArraySet;
 import android.util.Log;
@@ -136,6 +139,8 @@
     private final NetworkScoreManager mNetworkScoreManager;
     private final WifiNetworkScoreCache mScoreCache;
     private final Set<NetworkKey> mRequestedScores = new ArraySet<>();
+    private boolean mNetworkScoringUiEnabled;
+    private final ContentObserver mObserver;
 
     @VisibleForTesting
     Scanner mScanner;
@@ -215,6 +220,16 @@
                 Message.obtain(mWorkHandler, WorkHandler.MSG_UPDATE_NETWORK_SCORES).sendToTarget();
             }
         });
+
+        mObserver = new ContentObserver(mWorkHandler) {
+            @Override
+            public void onChange(boolean selfChange) {
+                mNetworkScoringUiEnabled =
+                        Settings.Global.getInt(
+                                mContext.getContentResolver(),
+                                Settings.Global.NETWORK_SCORING_UI_ENABLED, 0) == 1;
+            }
+        };
     }
 
     /**
@@ -274,6 +289,11 @@
             }
         });
 
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.NETWORK_SCORING_UI_ENABLED),
+                false /* notifyForDescendants */,
+                mObserver);
+        mObserver.onChange(false /* selfChange */); // Set the initial value for mScoringUiEnabled
 
         resumeScanning();
         if (!mRegistered) {
@@ -327,6 +347,7 @@
                 unregisterAndClearScoreCache();
             }
         });
+        mContext.getContentResolver().unregisterContentObserver(mObserver);
     }
 
     @WorkerThread
@@ -537,10 +558,11 @@
             }
         }
 
-
-        requestScoresForNetworkKeys(scoresToRequest);
-        for (AccessPoint ap : accessPoints) {
-            ap.updateScores(mScoreCache);
+        if (mNetworkScoringUiEnabled) {
+            requestScoresForNetworkKeys(scoresToRequest);
+            for (AccessPoint ap : accessPoints) {
+                ap.updateScores(mScoreCache);
+            }
         }
 
         // Pre-sort accessPoints to speed preference insertion
@@ -641,7 +663,7 @@
             if (ap.update(connectionConfig, mLastInfo, mLastNetworkInfo)) {
                 reorder = true;
             }
-            if (ap.updateScores(mScoreCache)) {
+            if (mNetworkScoringUiEnabled && ap.updateScores(mScoreCache)) {
                 reorder = true;
             }
         }
@@ -657,6 +679,10 @@
      * <p>Will trigger a resort and notify listeners of changes if applicable.
      */
     private void updateNetworkScores() {
+        if (!mNetworkScoringUiEnabled) {
+            return;
+        }
+
         // Lock required to prevent accidental copying of AccessPoint states while the modification
         // is in progress. see #copyAndNotifyListeners
         long before = System.currentTimeMillis();
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 eaf0367..08736c7 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
@@ -110,7 +110,7 @@
     private HandlerThread mWorkerThread;
     private Looper mLooper;
     private Looper mMainLooper;
-    private int mOriginalSettingValue;
+    private int mOriginalScoringUiSettingValue;
 
     @Before
     public void setUp() {
@@ -175,19 +175,23 @@
                   }
                 }).when(mockWifiListener).onAccessPointsChanged();
 
-        mOriginalSettingValue = Settings.Global.getInt(
-            InstrumentationRegistry.getTargetContext().getContentResolver(),
-            Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
-            0 /* disabled */);
-
+        // Turn on Scoring UI features
+        mOriginalScoringUiSettingValue = Settings.Global.getInt(
+                InstrumentationRegistry.getTargetContext().getContentResolver(),
+                Settings.Global.NETWORK_SCORING_UI_ENABLED,
+                0 /* disabled */);
+        Settings.Global.putInt(
+                InstrumentationRegistry.getTargetContext().getContentResolver(),
+                Settings.Global.NETWORK_SCORING_UI_ENABLED,
+                1 /* enabled */);
     }
 
     @After
     public void cleanUp() {
         Settings.Global.putInt(
-            InstrumentationRegistry.getTargetContext().getContentResolver(),
-            Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
-            mOriginalSettingValue);
+                InstrumentationRegistry.getTargetContext().getContentResolver(),
+                Settings.Global.NETWORK_SCORING_UI_ENABLED,
+                mOriginalScoringUiSettingValue);
     }
 
     private static ScanResult buildScanResult1() {
@@ -333,9 +337,18 @@
 
         WifiNetworkScoreCache scoreCache = mScoreCacheCaptor.getValue();
 
+        CountDownLatch latch = new CountDownLatch(1);
+        doAnswer(
+                (invocation) -> {
+                        latch.countDown();
+                        return null;
+                }).when(mockNetworkScoreManager)
+                        .unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, scoreCache);
+
         // Test unregister
         tracker.stopTracking();
 
+        latch.await(LATCH_TIMEOUT, TimeUnit.MILLISECONDS);
         verify(mockNetworkScoreManager)
                 .unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, scoreCache);
     }
@@ -385,7 +398,28 @@
         assertTrue(aps.size() == 2);
         assertEquals(aps.get(0).getSsidStr(), SSID_2);
         assertEquals(aps.get(1).getSsidStr(), SSID_1);
+    }
 
+    @Test
+    public void scoreCacheUpdateScoresShouldNotChangeSortOrderWhenSortingDisabled()
+            throws InterruptedException {
+        Settings.Global.putInt(
+                InstrumentationRegistry.getTargetContext().getContentResolver(),
+                Settings.Global.NETWORK_SCORING_UI_ENABLED,
+                0 /* disabled */);
+
+        WifiTracker tracker = createTrackerAndInjectInitialScanResults();
+        List<AccessPoint> aps = tracker.getAccessPoints();
+        assertTrue(aps.size() == 2);
+        assertEquals(aps.get(0).getSsidStr(), SSID_1);
+        assertEquals(aps.get(1).getSsidStr(), SSID_2);
+
+        updateScoresAndWaitForAccessPointsChangedCallback();
+
+        aps = tracker.getAccessPoints();
+        assertTrue(aps.size() == 2);
+        assertEquals(aps.get(0).getSsidStr(), SSID_1);
+        assertEquals(aps.get(1).getSsidStr(), SSID_2);
     }
 
     @Test
@@ -405,6 +439,28 @@
     }
 
     @Test
+    public void noBadgesShouldBeInsertedIntoAccessPointWhenScoringUiDisabled()
+            throws InterruptedException {
+        Settings.Global.putInt(
+                InstrumentationRegistry.getTargetContext().getContentResolver(),
+                Settings.Global.NETWORK_SCORING_UI_ENABLED,
+                0 /* disabled */);
+
+        WifiTracker tracker = createTrackerAndInjectInitialScanResults();
+        updateScoresAndWaitForAccessPointsChangedCallback();
+
+        List<AccessPoint> aps = tracker.getAccessPoints();
+
+        for (AccessPoint ap : aps) {
+            if (ap.getSsidStr().equals(SSID_1)) {
+                assertEquals(ScoredNetwork.BADGING_NONE, ap.getBadge());
+            } else if (ap.getSsidStr().equals(SSID_2)) {
+                assertEquals(ScoredNetwork.BADGING_NONE, ap.getBadge());
+            }
+        }
+    }
+
+    @Test
     public void scoresShouldBeRequestedForNewScanResultOnly()  throws InterruptedException {
         mRequestScoresLatch = new CountDownLatch(2);
         WifiTracker tracker = createTrackerAndInjectInitialScanResults();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 6979995..7a9ba20 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -80,16 +80,20 @@
 import java.io.FileNotFoundException;
 import java.io.PrintWriter;
 import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
+import java.nio.ByteBuffer;
+import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import java.util.regex.Pattern;
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
 
 import static android.os.Process.ROOT_UID;
 import static android.os.Process.SHELL_UID;
@@ -178,6 +182,18 @@
     private static final Bundle NULL_SETTING_BUNDLE = Bundle.forPair(
             Settings.NameValueTable.VALUE, null);
 
+    // Changes to these global settings are synchronously persisted
+    private static final Set<String> CRITICAL_GLOBAL_SETTINGS = new ArraySet<>();
+    static {
+        CRITICAL_GLOBAL_SETTINGS.add(Settings.Global.DEVICE_PROVISIONED);
+    }
+
+    // Changes to these secure settings are synchronously persisted
+    private static final Set<String> CRITICAL_SECURE_SETTINGS = new ArraySet<>();
+    static {
+        CRITICAL_SECURE_SETTINGS.add(Settings.Secure.USER_SETUP_COMPLETE);
+    }
+
     // Per user secure settings that moved to the for all users global settings.
     static final Set<String> sSecureMovedToGlobalSettings = new ArraySet<>();
     static {
@@ -945,18 +961,18 @@
                 case MUTATION_OPERATION_INSERT: {
                     return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_GLOBAL,
                             UserHandle.USER_SYSTEM, name, value, tag, makeDefault,
-                            getCallingPackage(), forceNotify);
+                            getCallingPackage(), forceNotify, CRITICAL_GLOBAL_SETTINGS);
                 }
 
                 case MUTATION_OPERATION_DELETE: {
                     return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_GLOBAL,
-                            UserHandle.USER_SYSTEM, name, forceNotify);
+                            UserHandle.USER_SYSTEM, name, forceNotify, CRITICAL_GLOBAL_SETTINGS);
                 }
 
                 case MUTATION_OPERATION_UPDATE: {
                     return mSettingsRegistry.updateSettingLocked(SETTINGS_TYPE_GLOBAL,
                             UserHandle.USER_SYSTEM, name, value, tag, makeDefault,
-                            getCallingPackage(), forceNotify);
+                            getCallingPackage(), forceNotify, CRITICAL_GLOBAL_SETTINGS);
                 }
 
                 case MUTATION_OPERATION_RESET: {
@@ -996,7 +1012,7 @@
                     continue;
                 }
 
-                // As of Android O (API 24), the SSAID is read from an app-specific entry in table
+                // As of Android O, the SSAID is read from an app-specific entry in table
                 // SETTINGS_FILE_SSAID, unless accessed by a system process.
                 final Setting setting;
                 if (isNewSsaidSetting(name)) {
@@ -1035,7 +1051,7 @@
 
         // Get the value.
         synchronized (mLock) {
-            // As of Android O (API 24), the SSAID is read from an app-specific entry in table
+            // As of Android O, the SSAID is read from an app-specific entry in table
             // SETTINGS_FILE_SSAID, unless accessed by a system process.
             if (isNewSsaidSetting(name)) {
                 return getSsaidSettingLocked(owningUserId);
@@ -1152,18 +1168,18 @@
                 case MUTATION_OPERATION_INSERT: {
                     return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SECURE,
                             owningUserId, name, value, tag, makeDefault,
-                            getCallingPackage(), forceNotify);
+                            getCallingPackage(), forceNotify, CRITICAL_SECURE_SETTINGS);
                 }
 
                 case MUTATION_OPERATION_DELETE: {
                     return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_SECURE,
-                            owningUserId, name, forceNotify);
+                            owningUserId, name, forceNotify, CRITICAL_SECURE_SETTINGS);
                 }
 
                 case MUTATION_OPERATION_UPDATE: {
                     return mSettingsRegistry.updateSettingLocked(SETTINGS_TYPE_SECURE,
                             owningUserId, name, value, tag, makeDefault,
-                            getCallingPackage(), forceNotify);
+                            getCallingPackage(), forceNotify, CRITICAL_SECURE_SETTINGS);
                 }
 
                 case MUTATION_OPERATION_RESET: {
@@ -1300,18 +1316,20 @@
                 case MUTATION_OPERATION_INSERT: {
                     validateSystemSettingValue(name, value);
                     return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SYSTEM,
-                            owningUserId, name, value, null, false, getCallingPackage(), false);
+                            owningUserId, name, value, null, false, getCallingPackage(),
+                            false, null);
                 }
 
                 case MUTATION_OPERATION_DELETE: {
                     return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_SYSTEM,
-                            owningUserId, name, false);
+                            owningUserId, name, false, null);
                 }
 
                 case MUTATION_OPERATION_UPDATE: {
                     validateSystemSettingValue(name, value);
                     return mSettingsRegistry.updateSettingLocked(SETTINGS_TYPE_SYSTEM,
-                            owningUserId, name, value, null, false, getCallingPackage(), false);
+                            owningUserId, name, value, null, false, getCallingPackage(),
+                            false, null);
                 }
             }
 
@@ -1685,7 +1703,7 @@
 
         return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_SECURE,
                 owningUserId, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, newProviders,
-                tag, makeDefault, getCallingPackage(), forceNotify);
+                tag, makeDefault, getCallingPackage(), forceNotify, CRITICAL_SECURE_SETTINGS);
     }
 
     private static void warnOrThrowForUndesiredSecureSettingsMutationForTargetSdk(
@@ -1978,12 +1996,12 @@
 
         private void generateUserKeyLocked(int userId) {
             // Generate a random key for each user used for creating a new ssaid.
-            final byte[] keyBytes = new byte[16];
+            final byte[] keyBytes = new byte[32];
             final SecureRandom rand = new SecureRandom();
             rand.nextBytes(keyBytes);
 
             // Convert to string for storage in settings table.
-            final String userKey = ByteStringUtils.toString(keyBytes);
+            final String userKey = ByteStringUtils.toHexString(keyBytes);
 
             // Store the key in the ssaid table.
             final SettingsState ssaidSettings = getSettingsLocked(SETTINGS_TYPE_SSAID, userId);
@@ -1995,6 +2013,10 @@
             }
         }
 
+        private byte[] getLengthPrefix(byte[] data) {
+            return ByteBuffer.allocate(4).putInt(data.length).array();
+        }
+
         public Setting generateSsaidLocked(String packageName, int userId) {
             final PackageInfo packageInfo;
             try {
@@ -2019,25 +2041,37 @@
             final String userKey = userKeySetting.getValue();
 
             // Convert the user's key back to a byte array.
-            final byte[] keyBytes = ByteStringUtils.toByteArray(userKey);
-            if (keyBytes == null || keyBytes.length != 16) {
+            final byte[] keyBytes = ByteStringUtils.fromHexToByteArray(userKey);
+
+            // Validate that the key is of expected length.
+            // Keys are currently 32 bytes, but were once 16 bytes during Android O development.
+            if (keyBytes == null || (keyBytes.length != 16 && keyBytes.length != 32)) {
                 throw new IllegalStateException("User key invalid");
             }
 
-            final MessageDigest md;
+            final Mac m;
             try {
-                // Hash package name and signature.
-                md = MessageDigest.getInstance("SHA-256");
+                m = Mac.getInstance("HmacSHA256");
+                m.init(new SecretKeySpec(keyBytes, m.getAlgorithm()));
             } catch (NoSuchAlgorithmException e) {
-                throw new IllegalStateException("HmacSHA256 is not available");
+                throw new IllegalStateException("HmacSHA256 is not available", e);
+            } catch (InvalidKeyException e) {
+                throw new IllegalStateException("Key is corrupted", e);
             }
-            md.update(keyBytes);
-            md.update(packageInfo.packageName.getBytes(StandardCharsets.UTF_8));
-            md.update(packageInfo.signatures[0].toByteArray());
+
+            // Mac the package name and each of the signatures.
+            byte[] packageNameBytes = packageInfo.packageName.getBytes(StandardCharsets.UTF_8);
+            m.update(getLengthPrefix(packageNameBytes), 0, 4);
+            m.update(packageNameBytes);
+            for (int i = 0; i < packageInfo.signatures.length; i++) {
+                byte[] sig = packageInfo.signatures[i].toByteArray();
+                m.update(getLengthPrefix(sig), 0, 4);
+                m.update(sig);
+            }
 
             // Convert result to a string for storage in settings table. Only want first 64 bits.
-            final String ssaid = ByteStringUtils.toString(md.digest()).substring(0, 16)
-                    .toLowerCase();
+            final String ssaid = ByteStringUtils.toHexString(m.doFinal()).substring(0, 16)
+                    .toLowerCase(Locale.US);
 
             // Save the ssaid in the ssaid table.
             final String uid = Integer.toString(packageInfo.applicationInfo.uid);
@@ -2214,7 +2248,8 @@
         }
 
         public boolean insertSettingLocked(int type, int userId, String name, String value,
-                String tag, boolean makeDefault, String packageName, boolean forceNotify) {
+                String tag, boolean makeDefault, String packageName, boolean forceNotify,
+                Set<String> criticalSettings) {
             final int key = makeKey(type, userId);
 
             boolean success = false;
@@ -2224,13 +2259,18 @@
                         tag, makeDefault, packageName);
             }
 
+            if (success && criticalSettings != null && criticalSettings.contains(name)) {
+                settingsState.persistSyncLocked();
+            }
+
             if (forceNotify || success) {
                 notifyForSettingsChange(key, name);
             }
             return success;
         }
 
-        public boolean deleteSettingLocked(int type, int userId, String name, boolean forceNotify) {
+        public boolean deleteSettingLocked(int type, int userId, String name, boolean forceNotify,
+                Set<String> criticalSettings) {
             final int key = makeKey(type, userId);
 
             boolean success = false;
@@ -2239,12 +2279,39 @@
                 success = settingsState.deleteSettingLocked(name);
             }
 
+            if (success && criticalSettings != null && criticalSettings.contains(name)) {
+                settingsState.persistSyncLocked();
+            }
+
             if (forceNotify || success) {
                 notifyForSettingsChange(key, name);
             }
             return success;
         }
 
+        public boolean updateSettingLocked(int type, int userId, String name, String value,
+                String tag, boolean makeDefault, String packageName, boolean forceNotify,
+                Set<String> criticalSettings) {
+            final int key = makeKey(type, userId);
+
+            boolean success = false;
+            SettingsState settingsState = peekSettingsStateLocked(key);
+            if (settingsState != null) {
+                success = settingsState.updateSettingLocked(name, value, tag,
+                        makeDefault, packageName);
+            }
+
+            if (success && criticalSettings != null && criticalSettings.contains(name)) {
+                settingsState.persistSyncLocked();
+            }
+
+            if (forceNotify || success) {
+                notifyForSettingsChange(key, name);
+            }
+
+            return success;
+        }
+
         public Setting getSettingLocked(int type, int userId, String name) {
             final int key = makeKey(type, userId);
 
@@ -2257,24 +2324,6 @@
             return settingsState.getSettingLocked(name);
         }
 
-        public boolean updateSettingLocked(int type, int userId, String name, String value,
-                String tag, boolean makeDefault, String packageName, boolean forceNotify) {
-            final int key = makeKey(type, userId);
-
-            boolean success = false;
-            SettingsState settingsState = peekSettingsStateLocked(key);
-            if (settingsState != null) {
-                success = settingsState.updateSettingLocked(name, value, tag,
-                        makeDefault, packageName);
-            }
-
-            if (forceNotify || success) {
-                notifyForSettingsChange(key, name);
-            }
-
-            return success;
-        }
-
         public void resetSettingsLocked(int type, int userId, String packageName, int mode,
                 String tag) {
             final int key = makeKey(type, userId);
@@ -2286,56 +2335,78 @@
             switch (mode) {
                 case Settings.RESET_MODE_PACKAGE_DEFAULTS: {
                     for (String name : settingsState.getSettingNamesLocked()) {
+                        boolean someSettingChanged = false;
                         Setting setting = settingsState.getSettingLocked(name);
                         if (packageName.equals(setting.getPackageName())) {
                             if (tag != null && !tag.equals(setting.getTag())) {
                                 continue;
                             }
-                            if (settingsState.resetSettingLocked(name, packageName)) {
+                            if (settingsState.resetSettingLocked(name)) {
+                                someSettingChanged = true;
                                 notifyForSettingsChange(key, name);
                             }
                         }
+                        if (someSettingChanged) {
+                            settingsState.persistSyncLocked();
+                        }
                     }
                 } break;
 
                 case Settings.RESET_MODE_UNTRUSTED_DEFAULTS: {
                     for (String name : settingsState.getSettingNamesLocked()) {
+                        boolean someSettingChanged = false;
                         Setting setting = settingsState.getSettingLocked(name);
                         if (!SettingsState.isSystemPackage(getContext(),
                                 setting.getPackageName())) {
-                            if (settingsState.resetSettingLocked(name, packageName)) {
+                            if (settingsState.resetSettingLocked(name)) {
+                                someSettingChanged = true;
                                 notifyForSettingsChange(key, name);
                             }
                         }
+                        if (someSettingChanged) {
+                            settingsState.persistSyncLocked();
+                        }
                     }
                 } break;
 
                 case Settings.RESET_MODE_UNTRUSTED_CHANGES: {
                     for (String name : settingsState.getSettingNamesLocked()) {
+                        boolean someSettingChanged = false;
                         Setting setting = settingsState.getSettingLocked(name);
                         if (!SettingsState.isSystemPackage(getContext(),
                                 setting.getPackageName())) {
                             if (setting.isDefaultFromSystem()) {
-                                if (settingsState.resetSettingLocked(name, packageName)) {
+                                if (settingsState.resetSettingLocked(name)) {
+                                    someSettingChanged = true;
                                     notifyForSettingsChange(key, name);
                                 }
                             } else if (settingsState.deleteSettingLocked(name)) {
+                                someSettingChanged = true;
                                 notifyForSettingsChange(key, name);
                             }
                         }
+                        if (someSettingChanged) {
+                            settingsState.persistSyncLocked();
+                        }
                     }
                 } break;
 
                 case Settings.RESET_MODE_TRUSTED_DEFAULTS: {
                     for (String name : settingsState.getSettingNamesLocked()) {
                         Setting setting = settingsState.getSettingLocked(name);
+                        boolean someSettingChanged = false;
                         if (setting.isDefaultFromSystem()) {
-                            if (settingsState.resetSettingLocked(name, packageName)) {
+                            if (settingsState.resetSettingLocked(name)) {
+                                someSettingChanged = true;
                                 notifyForSettingsChange(key, name);
                             }
                         } else if (settingsState.deleteSettingLocked(name)) {
+                            someSettingChanged = true;
                             notifyForSettingsChange(key, name);
                         }
+                        if (someSettingChanged) {
+                            settingsState.persistSyncLocked();
+                        }
                     }
                 } break;
             }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
index 2d59324..a6fadf9 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
@@ -113,7 +113,7 @@
         String mKey = null;
         String mValue = null;
         String mPackageName = null;
-        String mToken = null;
+        String mTag = null;
         int mResetMode = -1;
         boolean mMakeDefault;
 
@@ -185,7 +185,7 @@
                         if (peekNextArg() == null) {
                             valid = true;
                         } else {
-                            mToken = getNextArg();
+                            mTag = getNextArg();
                             if (peekNextArg() == null) {
                                 valid = true;
                             } else {
@@ -218,10 +218,10 @@
                     // what we have so far is a valid command
                     valid = true;
                     // keep going; there may be another PUT arg
-                } else if (mToken == null) {
-                    mToken = arg;
-                    if ("default".equalsIgnoreCase(mToken)) {
-                        mToken = null;
+                } else if (mTag == null) {
+                    mTag = arg;
+                    if ("default".equalsIgnoreCase(mTag)) {
+                        mTag = null;
                         mMakeDefault = true;
                         if (peekNextArg() == null) {
                             valid = true;
@@ -282,7 +282,7 @@
                     pout.println(getForUser(iprovider, mUser, mTable, mKey));
                     break;
                 case PUT:
-                    putForUser(iprovider, mUser, mTable, mKey, mValue, mToken, mMakeDefault);
+                    putForUser(iprovider, mUser, mTable, mKey, mValue, mTag, mMakeDefault);
                     break;
                 case DELETE:
                     pout.println("Deleted "
@@ -294,7 +294,7 @@
                     }
                     break;
                 case RESET:
-                    resetForUser(iprovider, mUser, mTable, mToken);
+                    resetForUser(iprovider, mUser, mTable, mTag);
                     break;
                 default:
                     perr.println("Unspecified command");
@@ -358,7 +358,7 @@
         }
 
         void putForUser(IContentProvider provider, int userHandle, final String table,
-                final String key, final String value, String token, boolean makeDefault) {
+                final String key, final String value, String tag, boolean makeDefault) {
             final String callPutCommand;
             if ("system".equals(table)) {
                 callPutCommand = Settings.CALL_METHOD_PUT_SYSTEM;
@@ -378,7 +378,9 @@
                 Bundle arg = new Bundle();
                 arg.putString(Settings.NameValueTable.VALUE, value);
                 arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
-                arg.putString(Settings.CALL_METHOD_TAG_KEY, token);
+                if (tag != null) {
+                    arg.putString(Settings.CALL_METHOD_TAG_KEY, tag);
+                }
                 if (makeDefault) {
                     arg.putBoolean(Settings.CALL_METHOD_MAKE_DEFAULT_KEY, true);
                 }
@@ -409,7 +411,7 @@
         }
 
         void resetForUser(IContentProvider provider, int userHandle,
-                String table, String token) {
+                String table, String tag) {
             final String callResetCommand;
             if ("secure".equals(table)) callResetCommand = Settings.CALL_METHOD_RESET_SECURE;
             else if ("global".equals(table)) callResetCommand = Settings.CALL_METHOD_RESET_GLOBAL;
@@ -422,7 +424,9 @@
                 Bundle arg = new Bundle();
                 arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
                 arg.putInt(Settings.CALL_METHOD_RESET_MODE_KEY, mResetMode);
-                arg.putString(Settings.CALL_METHOD_TAG_KEY, token);
+                if (tag != null) {
+                    arg.putString(Settings.CALL_METHOD_TAG_KEY, tag);
+                }
                 String packageName = mPackageName != null ? mPackageName : resolveCallingPackage();
                 arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
                 provider.call(packageName, callResetCommand, null, arg);
@@ -465,9 +469,9 @@
                 pw.println("      Print this help text.");
                 pw.println("  get [--user <USER_ID> | current] NAMESPACE KEY");
                 pw.println("      Retrieve the current value of KEY.");
-                pw.println("  put [--user <USER_ID> | current] NAMESPACE KEY VALUE [TOKEN] [default]");
+                pw.println("  put [--user <USER_ID> | current] NAMESPACE KEY VALUE [TAG] [default]");
                 pw.println("      Change the contents of KEY to VALUE.");
-                pw.println("      TOKEN to associate with the setting.");
+                pw.println("      TAG to associate with the setting.");
                 pw.println("      {default} to set as the default, case-insensitive only for global/secure namespace");
                 pw.println("  delete NAMESPACE KEY");
                 pw.println("      Delete the entry for KEY.");
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index a74be35..56ae618 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -64,6 +64,7 @@
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 /**
  * This class contains the state for one type of settings. It is responsible
@@ -129,7 +130,7 @@
     private static final String HISTORICAL_OPERATION_INITIALIZE = "initialize";
     private static final String HISTORICAL_OPERATION_RESET = "reset";
 
-    private static final String SHELL_PACKAGE_NAME = "shell";
+    private static final String SHELL_PACKAGE_NAME = "com.android.shell";
     private static final String ROOT_PACKAGE_NAME = "root";
 
     private static final String NULL_VALUE = "null";
@@ -307,7 +308,7 @@
         Setting newState;
 
         if (oldState != null) {
-            if (!oldState.update(value, makeDefault, packageName, tag)) {
+            if (!oldState.update(value, makeDefault, packageName, tag, false)) {
                 return false;
             }
             newState = oldState;
@@ -351,7 +352,7 @@
     }
 
     // The settings provider must hold its lock when calling here.
-    public boolean resetSettingLocked(String name, String packageName) {
+    public boolean resetSettingLocked(String name) {
         if (TextUtils.isEmpty(name) || !hasSettingLocked(name)) {
             return false;
         }
@@ -362,7 +363,7 @@
         String oldValue = setting.getValue();
         String oldDefaultValue = setting.getDefaultValue();
 
-        if (!setting.reset(packageName)) {
+        if (!setting.reset()) {
             return false;
         }
 
@@ -817,7 +818,7 @@
         public Setting(String name, String value, boolean makeDefault, String packageName,
                 String tag) {
             this.name = name;
-            update(value, makeDefault, packageName, tag);
+            update(value, makeDefault, packageName, tag, false);
         }
 
         public Setting(String name, String value, String defaultValue,
@@ -877,16 +878,18 @@
         }
 
         /** @return whether the value changed */
-        public boolean reset(String packageName) {
-            return update(this.defaultValue, false, packageName, null);
+        public boolean reset() {
+            return update(this.defaultValue, false, packageName, null, true);
         }
 
-        public boolean update(String value, boolean setDefault, String packageName, String tag) {
+        public boolean update(String value, boolean setDefault, String packageName, String tag,
+                boolean forceNonSystemPackage) {
             if (NULL_VALUE.equals(value)) {
                 value = null;
             }
 
-            final boolean callerSystem = !isNull() && isSystemPackage(mContext, packageName);
+            final boolean callerSystem = !forceNonSystemPackage &&
+                    !isNull() && isSystemPackage(mContext, packageName);
             // Settings set by the system are always defaults.
             if (callerSystem) {
                 setDefault = true;
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java
index 0454b51..ab23af3 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/BaseSettingsProviderTest.java
@@ -206,19 +206,22 @@
         resetToDefaultsViaShell(type, packageName, null);
     }
 
-    protected static void resetToDefaultsViaShell(int type, String packageName, String token)
+    protected static void resetToDefaultsViaShell(int type, String packageName, String tag)
             throws IOException {
         switch (type) {
             case SETTING_TYPE_GLOBAL: {
-                executeShellCommand("settings reset global " + packageName + " " + token);
+                executeShellCommand("settings reset global " + packageName + " "
+                        + (tag != null ? tag : ""));
             } break;
 
             case SETTING_TYPE_SECURE: {
-                executeShellCommand("settings reset secure " + packageName + " " + token);
+                executeShellCommand("settings reset secure " + packageName + " "
+                        + (tag != null ? tag : ""));
             } break;
 
             case SETTING_TYPE_SYSTEM: {
-                executeShellCommand("settings reset system " + packageName + " " + token);
+                executeShellCommand("settings reset system " + packageName + " "
+                        + (tag != null ? tag : ""));
             } break;
 
             default: {
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index f72d091..4b8734f 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -500,7 +500,6 @@
                   android:label="@string/accessibility_desc_work_lock"
                   android:permission="android.permission.MANAGE_USERS"
                   android:exported="false"
-                  android:launchMode="singleTop"
                   android:excludeFromRecents="true"
                   android:stateNotNeeded="true"
                   android:resumeWhilePausing="true"
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/Plugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/Plugin.java
index b31b199..e75ecb7 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/Plugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/Plugin.java
@@ -64,7 +64,7 @@
  *        new PluginListener<OverlayPlugin>() {
  *        @Override
  *        public void onPluginConnected(OverlayPlugin plugin) {
- *            PhoneStatusBar phoneStatusBar = getComponent(PhoneStatusBar.class);
+ *            StatusBar phoneStatusBar = getComponent(StatusBar.class);
  *            if (phoneStatusBar != null) {
  *                plugin.setup(phoneStatusBar.getStatusBarWindow(),
  *                phoneStatusBar.getNavigationBarView());
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java
index 9f44bd4..d71b6bd 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginInstanceManager.java
@@ -51,6 +51,9 @@
     private static final String TAG = "PluginInstanceManager";
     private static final String PLUGIN_PERMISSION = "com.android.systemui.permission.PLUGIN";
 
+    // must be one of the channels created in NotificationChannels.java
+    private static final String NOTIFICATION_CHANNEL_ID = "ALR";
+
     private final Context mContext;
     private final PluginListener<T> mListener;
     private final String mAction;
@@ -312,7 +315,7 @@
                             .setSmallIcon(icon)
                             .setWhen(0)
                             .setShowWhen(false)
-                            .setPriority(Notification.PRIORITY_MAX)
+                            .setChannel(NOTIFICATION_CHANNEL_ID)
                             .setVisibility(Notification.VISIBILITY_PUBLIC)
                             .setColor(mContext.getColor(color));
                     String label = cls;
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowProvider.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowProvider.java
new file mode 100644
index 0000000..93ba39c
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowProvider.java
@@ -0,0 +1,90 @@
+
+package com.android.systemui.plugins.statusbar;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.service.notification.SnoozeCriterion;
+import android.service.notification.StatusBarNotification;
+import android.view.View;
+
+import java.util.ArrayList;
+
+import com.android.systemui.plugins.Plugin;
+
+public interface NotificationMenuRowProvider extends Plugin {
+
+    public static final String ACTION = "com.android.systemui.action.PLUGIN_NOTIFICATION_MENU_ROW";
+
+    public static final int VERSION = 1;
+
+    /**
+     * Returns a list of items to populate the menu 'behind' a notification.
+     */
+    public ArrayList<MenuItem> getMenuItems(Context context);
+
+    public interface OnMenuClickListener {
+        public void onMenuClicked(View row, int x, int y, MenuItem menu);
+
+        public void onMenuReset(View row);
+    }
+
+    public interface GutsInteractionListener {
+        public void onInteraction(View view);
+
+        public void closeGuts(View view);
+    }
+
+    public interface GutsContent {
+        public void setInteractionListener(GutsInteractionListener listener);
+
+        public View getContentView();
+
+        public boolean handleCloseControls();
+    }
+
+    public interface SnoozeGutsContent extends GutsContent {
+        public void setSnoozeListener(SnoozeListener listener);
+
+        public void setStatusBarNotification(StatusBarNotification sbn);
+    }
+
+    public interface SnoozeListener {
+        public void snoozeNotification(StatusBarNotification sbn, SnoozeOption snoozeOption);
+    }
+
+    public static class MenuItem {
+        public Drawable icon;
+        public String menuDescription;
+        public View menuView;
+        public GutsContent gutsContent;
+
+        public MenuItem(Drawable i, String s, GutsContent content) {
+            icon = i;
+            menuDescription = s;
+            gutsContent = content;
+        }
+
+        public View getGutsView() {
+            return gutsContent.getContentView();
+        }
+
+        public boolean onTouch(View v, int x, int y) {
+            return false;
+        }
+    }
+
+    public static class SnoozeOption {
+        public SnoozeCriterion criterion;
+        public int snoozeForMinutes;
+        public CharSequence description;
+        public CharSequence confirmation;
+
+        public SnoozeOption(SnoozeCriterion crit, int minsToSnoozeFor, CharSequence desc,
+                CharSequence confirm) {
+            criterion = crit;
+            snoozeForMinutes = minsToSnoozeFor;
+            description = desc;
+            confirmation = confirm;
+        }
+    }
+}
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 364885a..6d76798 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -11,7 +11,7 @@
 }
 
 -keep class com.android.systemui.statusbar.car.CarStatusBar
--keep class com.android.systemui.statusbar.phone.PhoneStatusBar
+-keep class com.android.systemui.statusbar.phone.StatusBar
 -keep class com.android.systemui.statusbar.tv.TvStatusBar
 -keep class com.android.systemui.car.CarSystemUIFactory
 -keep class com.android.systemui.SystemUIFactory
diff --git a/packages/SystemUI/res/drawable/ic_left.xml b/packages/SystemUI/res/drawable/ic_left.xml
new file mode 100644
index 0000000..cea4cfc
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_left.xml
@@ -0,0 +1,24 @@
+<!--
+    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="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M15.41,16.09l-4.58,-4.59 4.58,-4.59L14.0,5.5l-6.0,6.0 6.0,6.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_menu.xml b/packages/SystemUI/res/drawable/ic_menu.xml
new file mode 100644
index 0000000..994bc5e
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_menu.xml
@@ -0,0 +1,24 @@
+<!--
+    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="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M3.0,18.0l18.0,0.0l0.0,-2.0L3.0,16.0l0.0,2.0zm0.0,-5.0l18.0,0.0l0.0,-2.0L3.0,11.0l0.0,2.0zm0.0,-7.0l0.0,2.0l18.0,0.0L21.0,6.0L3.0,6.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_r.xml b/packages/SystemUI/res/drawable/ic_qs_signal_r.xml
deleted file mode 100644
index 40bfbe6..0000000
--- a/packages/SystemUI/res/drawable/ic_qs_signal_r.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-Copyright (C) 2014 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="32.0dp"
-        android:height="32dp"
-        android:viewportWidth="6.0"
-        android:viewportHeight="6.0">
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M2.800000,7.900000l-1.000000,0.000000L1.800000,11.000000L0.200000,11.000000L0.200000,2.500000l2.700000,0.000000c0.900000,0.000000 1.500000,0.200000 2.000000,0.700000s0.700000,1.100000 0.700000,1.900000c0.000000,0.600000 -0.100000,1.100000 -0.300000,1.500000S4.800000,7.200000 4.400000,7.400000l1.500000,3.500000L5.900000,11.000000L4.100000,11.000000L2.800000,7.900000zM1.800000,6.500000l1.100000,0.000000c0.400000,0.000000 0.600000,-0.100000 0.800000,-0.400000S4.000000,5.600000 4.000000,5.200000c0.000000,-0.400000 -0.100000,-0.800000 -0.300000,-1.000000S3.300000,3.800000 2.900000,3.800000L1.800000,3.800000L1.800000,6.500000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_remove.xml b/packages/SystemUI/res/drawable/ic_remove.xml
new file mode 100644
index 0000000..75b2793
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_remove.xml
@@ -0,0 +1,24 @@
+<!--
+    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="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M19.0,13.0L5.0,13.0l0.0,-2.0l14.0,0.0l0.0,2.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_right.xml b/packages/SystemUI/res/drawable/ic_right.xml
new file mode 100644
index 0000000..35699f73
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_right.xml
@@ -0,0 +1,24 @@
+<!--
+    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="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M8.59,16.34l4.58,-4.59 -4.58,-4.59L10.0,5.75l6.0,6.0 -6.0,6.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_snooze.xml b/packages/SystemUI/res/drawable/ic_snooze.xml
new file mode 100644
index 0000000..b0b03a9
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_snooze.xml
@@ -0,0 +1,12 @@
+<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:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8z"
+        android:fillColor="#757575"/>
+    <path
+        android:pathData="M12.5,7H11v6l5.25,3.15 0.75,-1.23 -4.5,-2.67z"
+        android:fillColor="#757575"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_roam.xml b/packages/SystemUI/res/drawable/stat_sys_roaming.xml
similarity index 95%
rename from packages/SystemUI/res/drawable/stat_sys_data_fully_connected_roam.xml
rename to packages/SystemUI/res/drawable/stat_sys_roaming.xml
index 363e231..4baa472 100644
--- a/packages/SystemUI/res/drawable/stat_sys_data_fully_connected_roam.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_roaming.xml
@@ -14,10 +14,10 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="4.25dp"
+        android:width="8.5dp"
         android:height="17dp"
         android:viewportWidth="6.0"
-        android:viewportHeight="24.0">
+        android:viewportHeight="12.0">
     <path
         android:fillColor="#FFFFFFFF"
         android:pathData="M2.800000,7.900000l-1.000000,0.000000L1.800000,11.000000L0.200000,11.000000L0.200000,2.500000l2.700000,0.000000c0.900000,0.000000 1.500000,0.200000 2.000000,0.700000s0.700000,1.100000 0.700000,1.900000c0.000000,0.600000 -0.100000,1.100000 -0.300000,1.500000S4.800000,7.200000 4.400000,7.400000l1.500000,3.500000L5.900000,11.000000L4.100000,11.000000L2.800000,7.900000zM1.800000,6.500000l1.100000,0.000000c0.400000,0.000000 0.600000,-0.100000 0.800000,-0.400000S4.000000,5.600000 4.000000,5.200000c0.000000,-0.400000 -0.100000,-0.800000 -0.300000,-1.000000S3.300000,3.800000 2.900000,3.800000L1.800000,3.800000L1.800000,6.500000z"/>
diff --git a/packages/SystemUI/res/layout/data_usage.xml b/packages/SystemUI/res/layout/data_usage.xml
index c943f3d..fdc6f14 100644
--- a/packages/SystemUI/res/layout/data_usage.xml
+++ b/packages/SystemUI/res/layout/data_usage.xml
@@ -59,6 +59,7 @@
             android:layout_height="wrap_content"
             android:layout_weight="1"
             android:textAppearance="@style/TextAppearance.QS.DataUsage" />
+
     </LinearLayout>
 
     <LinearLayout
@@ -82,4 +83,13 @@
             android:textAppearance="@style/TextAppearance.QS.DataUsage.Secondary" />
     </LinearLayout>
 
-</com.android.systemui.qs.tiles.DataUsageDetailView>
\ No newline at end of file
+    <TextView
+        android:id="@+id/roaming_text"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingTop="16dp"
+        android:text="@string/accessibility_data_connection_roaming"
+        android:textAppearance="@style/TextAppearance.QS.DataUsage.Secondary"
+        android:visibility="gone" />
+
+</com.android.systemui.qs.tiles.DataUsageDetailView>
diff --git a/packages/SystemUI/res/layout/mobile_signal_group.xml b/packages/SystemUI/res/layout/mobile_signal_group.xml
index a20ec8e..8b10074 100644
--- a/packages/SystemUI/res/layout/mobile_signal_group.xml
+++ b/packages/SystemUI/res/layout/mobile_signal_group.xml
@@ -43,4 +43,15 @@
         android:layout_height="wrap_content"
         android:layout_width="wrap_content"
         />
+    <ImageView
+        android:id="@+id/mobile_roaming"
+        android:layout_width="wrap_content"
+        android:layout_height="17dp"
+        android:paddingStart="22dp"
+        android:paddingTop="1.5dp"
+        android:paddingBottom="3dp"
+        android:scaleType="fitCenter"
+        android:src="@drawable/stat_sys_roaming"
+        android:contentDescription="@string/accessibility_data_connection_roaming"
+        android:visibility="gone" />
 </FrameLayout>
diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml
index 3948dc4..9d8ef83 100644
--- a/packages/SystemUI/res/layout/notification_guts.xml
+++ b/packages/SystemUI/res/layout/notification_guts.xml
@@ -23,125 +23,4 @@
     android:visibility="gone"
     android:clickable="true"
     android:gravity="top|start"
-    android:orientation="vertical"
-    android:paddingStart="@*android:dimen/notification_content_margin_start"
-    android:paddingEnd="8dp"
-    android:background="@color/notification_guts_bg_color"
-    android:theme="@*android:style/Theme.DeviceDefault.Light">
-
-    <!-- header -->
-    <RelativeLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingTop="20dp"
-        android:paddingEnd="8dp"
-        android:paddingBottom="15dp"
-        android:id="@+id/notification_guts_header">
-        <TextView
-            android:id="@+id/pkgname"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentStart="true"
-            style="@style/TextAppearance.NotificationGuts.Secondary" />
-        <TextView
-            android:id="@+id/channel_name"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentStart="true"
-            android:layout_below="@id/pkgname"
-            style="@style/TextAppearance.NotificationGuts.Header" />
-        <Switch
-            android:id="@+id/channel_enabled_switch"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_alignParentRight="true"
-            android:layout_centerVertical="true"
-            android:background="@null" />
-    </RelativeLayout>
-    <!-- Importance radio buttons -->
-    <LinearLayout
-        android:id="@+id/importance"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal">
-        <RadioGroup
-            android:id="@+id/importance_buttons"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:paddingEnd="@*android:dimen/notification_content_margin_end">
-            <RadioButton
-                android:id="@+id/high_importance"
-                android:layout_width="wrap_content"
-                android:layout_height="@dimen/notification_inline_importance_height"
-                style="@style/TextAppearance.NotificationGuts.Radio"
-                android:buttonTint="@color/notification_guts_buttons" />
-            <RadioButton
-                android:id="@+id/default_importance"
-                android:layout_width="wrap_content"
-                android:layout_height="@dimen/notification_inline_importance_height"
-                style="@style/TextAppearance.NotificationGuts.Radio"
-                android:buttonTint="@color/notification_guts_buttons" />
-            <RadioButton
-                android:id="@+id/low_importance"
-                android:layout_width="wrap_content"
-                android:layout_height="@dimen/notification_inline_importance_height"
-                style="@style/TextAppearance.NotificationGuts.Radio"
-                android:buttonTint="@color/notification_guts_buttons" />
-            <RadioButton
-                android:id="@+id/min_importance"
-                android:layout_width="wrap_content"
-                android:layout_height="@dimen/notification_inline_importance_height"
-                style="@style/TextAppearance.NotificationGuts.Radio"
-                android:buttonTint="@color/notification_guts_buttons" />
-        </RadioGroup>
-        <LinearLayout
-            android:id="@+id/importance_buttons_text"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical">
-            <include layout="@layout/notification_guts_importance_text"/>
-            <include layout="@layout/notification_guts_importance_text"/>
-            <include layout="@layout/notification_guts_importance_text"/>
-            <include layout="@layout/notification_guts_importance_text"/>
-        </LinearLayout>
-    </LinearLayout>
-    <!-- Channel Disabled Text -->
-    <TextView
-        android:id="@+id/channel_disabled"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:text="@string/notification_channel_disabled"
-        style="@style/TextAppearance.NotificationGuts.Secondary" />
-    <!-- Settings and Done buttons -->
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:gravity="end"
-        android:paddingTop="16dp"
-        android:paddingBottom="8dp" >
-
-        <TextView
-            android:id="@+id/more_settings"
-            android:text="@string/notification_more_settings"
-            android:layout_width="wrap_content"
-            android:layout_height="36dp"
-            style="@style/TextAppearance.NotificationGuts.Button"
-            android:background="@drawable/btn_borderless_rect"
-            android:gravity="center"
-            android:paddingEnd="8dp"
-            android:paddingStart="8dp"
-            android:focusable="true" />
-
-        <TextView
-            android:id="@+id/done"
-            android:text="@string/notification_done"
-            android:layout_width="wrap_content"
-            android:layout_height="36dp"
-            style="@style/TextAppearance.NotificationGuts.Button"
-            android:background="@drawable/btn_borderless_rect"
-            android:gravity="center"
-            android:layout_marginStart="8dp"
-            android:layout_marginEnd="8dp"
-            android:focusable="true"/>
-    </LinearLayout>
-</com.android.systemui.statusbar.NotificationGuts>
+    android:theme="@*android:style/Theme.DeviceDefault.Light"/>
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
new file mode 100644
index 0000000..9770ecc
--- /dev/null
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+
+<com.android.systemui.statusbar.NotificationInfo
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:id="@+id/notification_guts"
+        android:clickable="true"
+        android:gravity="top|start"
+        android:orientation="vertical"
+        android:paddingStart="@*android:dimen/notification_content_margin_start"
+        android:paddingEnd="8dp"
+        android:background="@color/notification_guts_bg_color"
+        android:theme="@*android:style/Theme.DeviceDefault.Light">
+
+    <!-- header -->
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="20dp"
+        android:paddingEnd="8dp"
+        android:paddingBottom="15dp"
+        android:id="@+id/notification_guts_header">
+        <TextView
+            android:id="@+id/pkgname"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentStart="true"
+            style="@style/TextAppearance.NotificationGuts.Secondary" />
+        <TextView
+            android:id="@+id/channel_name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentStart="true"
+            android:layout_below="@id/pkgname"
+            style="@style/TextAppearance.NotificationGuts.Header" />
+        <Switch
+            android:id="@+id/channel_enabled_switch"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentRight="true"
+            android:layout_centerVertical="true"
+            android:background="@null" />
+    </RelativeLayout>
+    <!-- Importance radio buttons -->
+    <LinearLayout
+        android:id="@+id/importance"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal">
+        <RadioGroup
+            android:id="@+id/importance_buttons"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingEnd="@*android:dimen/notification_content_margin_end">
+            <RadioButton
+                android:id="@+id/high_importance"
+                android:layout_width="wrap_content"
+                android:layout_height="@dimen/notification_inline_importance_height"
+                style="@style/TextAppearance.NotificationGuts.Radio"
+                android:buttonTint="@color/notification_guts_buttons" />
+            <RadioButton
+                android:id="@+id/default_importance"
+                android:layout_width="wrap_content"
+                android:layout_height="@dimen/notification_inline_importance_height"
+                style="@style/TextAppearance.NotificationGuts.Radio"
+                android:buttonTint="@color/notification_guts_buttons" />
+            <RadioButton
+                android:id="@+id/low_importance"
+                android:layout_width="wrap_content"
+                android:layout_height="@dimen/notification_inline_importance_height"
+                style="@style/TextAppearance.NotificationGuts.Radio"
+                android:buttonTint="@color/notification_guts_buttons" />
+            <RadioButton
+                android:id="@+id/min_importance"
+                android:layout_width="wrap_content"
+                android:layout_height="@dimen/notification_inline_importance_height"
+                style="@style/TextAppearance.NotificationGuts.Radio"
+                android:buttonTint="@color/notification_guts_buttons" />
+        </RadioGroup>
+        <LinearLayout
+            android:id="@+id/importance_buttons_text"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical">
+            <include layout="@layout/notification_guts_importance_text"/>
+            <include layout="@layout/notification_guts_importance_text"/>
+            <include layout="@layout/notification_guts_importance_text"/>
+            <include layout="@layout/notification_guts_importance_text"/>
+        </LinearLayout>
+    </LinearLayout>
+    <!-- Channel Disabled Text -->
+    <TextView
+        android:id="@+id/channel_disabled"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/notification_channel_disabled"
+        style="@style/TextAppearance.NotificationGuts.Secondary" />
+    <!-- Settings and Done buttons -->
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="end"
+        android:paddingTop="16dp"
+        android:paddingBottom="8dp" >
+
+        <TextView
+            android:id="@+id/more_settings"
+            android:text="@string/notification_more_settings"
+            android:layout_width="wrap_content"
+            android:layout_height="36dp"
+            style="@style/TextAppearance.NotificationGuts.Button"
+            android:background="@drawable/btn_borderless_rect"
+            android:gravity="center"
+            android:paddingEnd="8dp"
+            android:paddingStart="8dp"
+            android:focusable="true" />
+
+        <TextView
+            android:id="@+id/done"
+            android:text="@string/notification_done"
+            android:layout_width="wrap_content"
+            android:layout_height="36dp"
+            style="@style/TextAppearance.NotificationGuts.Button"
+            android:background="@drawable/btn_borderless_rect"
+            android:gravity="center"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
+            android:focusable="true"/>
+    </LinearLayout>
+</com.android.systemui.statusbar.NotificationInfo>
diff --git a/packages/SystemUI/res/layout/notification_menu_row.xml b/packages/SystemUI/res/layout/notification_menu_row.xml
new file mode 100644
index 0000000..12bcf81
--- /dev/null
+++ b/packages/SystemUI/res/layout/notification_menu_row.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright 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.
+-->
+<com.android.systemui.statusbar.NotificationMenuRow
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:visibility="invisible"/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/notification_settings_icon_row.xml b/packages/SystemUI/res/layout/notification_settings_icon_row.xml
deleted file mode 100644
index da3461b90..0000000
--- a/packages/SystemUI/res/layout/notification_settings_icon_row.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-    Copyright 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.
--->
-<com.android.systemui.statusbar.NotificationSettingsIconRow
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res-auto"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:visibility="invisible"
-    >
-
-    <com.android.systemui.statusbar.AlphaOptimizedImageView
-        android:id="@+id/gear_icon"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:padding="@dimen/notification_gear_padding"
-        android:src="@drawable/ic_settings"
-        android:tint="@color/notification_gear_color"
-        android:alpha="0"
-        android:background="?android:attr/selectableItemBackgroundBorderless"
-        />
-
-</com.android.systemui.statusbar.NotificationSettingsIconRow>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/notification_snooze.xml b/packages/SystemUI/res/layout/notification_snooze.xml
new file mode 100644
index 0000000..5bd64de
--- /dev/null
+++ b/packages/SystemUI/res/layout/notification_snooze.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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.
+-->
+
+<com.android.systemui.statusbar.NotificationSnooze
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="@dimen/snooze_snackbar_min_height"
+    android:id="@+id/notification_snooze"
+    android:clickable="true"
+    android:gravity="center_vertical"
+    android:orientation="horizontal"
+    android:paddingStart="24dp"
+    android:paddingEnd="24dp"
+    android:background="@color/snooze_snackbar_bg">
+    
+    <TextView
+        android:id="@+id/snooze_option_default"
+        style="@style/TextAppearance.SnoozeSnackBar"
+        android:layout_width="wrap_content"
+       	android:layout_height="match_parent"
+       	android:gravity="center_vertical"
+      	android:drawableTint="@android:color/white"
+       	android:drawableEnd="@drawable/notification_expand_more"/>
+    
+    <android.widget.Space
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        />
+    
+    <TextView
+        android:id="@+id/undo"
+        style="@style/TextAppearance.SnoozeSnackBar.Button"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_marginEnd="8dp"
+        android:layout_marginStart="8dp"
+        android:background="@drawable/btn_borderless_rect"
+        android:layout_gravity="end"
+        android:text="@string/snooze_undo" />
+    
+    <LinearLayout
+        android:id="@+id/snooze_options"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="8dp"
+        android:paddingBottom="8dp"
+        android:orientation="vertical"/>
+    
+</com.android.systemui.statusbar.NotificationSnooze>
diff --git a/packages/SystemUI/res/layout/recents_task_view_header.xml b/packages/SystemUI/res/layout/recents_task_view_header.xml
index 789b765..5ee242d 100644
--- a/packages/SystemUI/res/layout/recents_task_view_header.xml
+++ b/packages/SystemUI/res/layout/recents_task_view_header.xml
@@ -23,6 +23,7 @@
     android:layout_gravity="top|center_horizontal">
     <com.android.systemui.recents.views.FixedSizeImageView
         android:id="@+id/icon"
+        android:contentDescription="@string/recents_app_info_button_label"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical|start"
diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml
index e456984..d62cc18 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml
@@ -24,10 +24,10 @@
     >
 
     <ViewStub
-        android:layout="@layout/notification_settings_icon_row"
-        android:id="@+id/settings_icon_row_stub"
-        android:inflatedId="@+id/notification_settings_icon_row"
-        android:layout_width="wrap_content"
+        android:layout="@layout/notification_menu_row"
+        android:id="@+id/menu_row_stub"
+        android:inflatedId="@+id/notification_menu_row"
+        android:layout_width="match_parent"
         android:layout_height="match_parent"
         />
 
diff --git a/packages/SystemUI/res/layout/tuner_shortcut_item.xml b/packages/SystemUI/res/layout/tuner_shortcut_item.xml
new file mode 100644
index 0000000..e9eae3b
--- /dev/null
+++ b/packages/SystemUI/res/layout/tuner_shortcut_item.xml
@@ -0,0 +1,47 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="48dp"
+    android:paddingStart="4dp"
+    android:paddingEnd="4dp"
+    android:clickable="true"
+    android:gravity="center"
+    android:background="?android:attr/selectableItemBackground">
+
+    <ImageView
+        android:id="@android:id/icon"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:padding="12dp" />
+
+    <TextView android:id="@android:id/title"
+        android:layout_height="wrap_content"
+        android:layout_width="0dp"
+        android:layout_weight="1"
+        android:layout_gravity="center_vertical"
+        android:textAppearance="?android:attr/textAppearanceListItem"
+        android:textColor="?android:attr/textColorPrimary" />
+
+    <com.android.systemui.statusbar.phone.ExpandableIndicator
+        android:id="@+id/expand"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:padding="12dp"
+        android:visibility="gone" />
+
+</LinearLayout>
diff --git a/libs/androidfw/tests/data/lib/AndroidManifest.xml b/packages/SystemUI/res/layout/tuner_shortcut_list.xml
similarity index 66%
copy from libs/androidfw/tests/data/lib/AndroidManifest.xml
copy to packages/SystemUI/res/layout/tuner_shortcut_list.xml
index 02f5d3e..9aaffb4 100644
--- a/libs/androidfw/tests/data/lib/AndroidManifest.xml
+++ b/packages/SystemUI/res/layout/tuner_shortcut_list.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- 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.
@@ -14,7 +14,9 @@
      limitations under the License.
 -->
 
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.lib">
-    <application />
-</manifest>
+<android.support.v7.widget.RecyclerView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="200dp"
+    android:gravity="center" />
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 9744eb3..d145f7e 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -340,16 +340,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Verdeel horisontaal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Verdeel vertikaal"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Verdeel gepasmaak"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Maak toe"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Maak oop"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Verdeel skerm na bo"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Verdeel skerm na links"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Verdeel skerm na regs"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Gelaai"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index b3354f1..c2bd45f 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"የ<xliff:g id="DATA_LIMIT">%s</xliff:g> ማስጠንቀቂያ"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"የሥራ ሁነታ"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"የምሽት ብርሃን"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"ኤንኤፍሲ"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"ኤንኤፍሲ ተሰናክሏል"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"ኤንኤፍሲ ነቅቷል"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"ምንም የቅርብ ጊዜ ንጥሎች የሉም"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"ሁሉንም ነገር አጽድተዋል"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"የመተግበሪያ መረጃ"</string>
@@ -340,16 +337,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"አሰናብት"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"ክፈት"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ባትሪ ሞልቷል"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"የVPN ግንኙነት አቋርጥ"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"እርስዎ ኢሜይሎችን፣ መተግበሪያዎችን እና ድር ጣቢያዎችንም ጨምሮ የግል የአውታረ መረብ እንቅስቃሴዎን መከታተል ከሚችለው <xliff:g id="VPN_APP">%1$s</xliff:g> ጋር ተገናኝተዋል።"</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"የVPN ቅንብሮችን ይክፈቱ"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"የእርስዎ አስተዳዳሪ የአውታረ መረብ ምዝግብ ማስታወሻ መያዝን አብርተዋል፣ ይህም በመሣሪያዎ ላይ ያለውን ትራፊክ ይከታተላል።\n\nተጨማሪ መረጃ ለማግኘት አስተዳዳሪዎን ያነጋግሩ።"</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"አንድ መተግበሪያ የVPN ግንኙነት እንዲያዋቅር ፍቃድ ሰጥተውታል።\n\nይህ መተግበሪያ ኢሜይሎችን፣ መተግበሪያዎችን እና ድር ጣቢያዎችንም ጨምሮ የመሣሪያዎን እና የአውታረ መረብ እንቅስቃሴዎን መከታተል ይችላል።"</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"የእርስዎ የስራ መገለጫ በ<xliff:g id="ORGANIZATION">%1$s</xliff:g> ነው የሚቀናበረው።\n\nየእርስዎ አስተዳዳሪ ኢሜይሎችን፣ መተግበሪያዎችን እና ድር ጣቢያዎችን ጨምሮ የአውታረ መረብ እንቅስቃሴዎን መከታተል ይችላል።\n\nተጨማሪ መረጃ ለማግኘት አስተዳዳሪዎን ያነጋግሩ።\n\nእርስዎ እንዲሁም የአውታረ መረብ እንቅስቃሴዎን መከታተል ከሚችል ቪፒኤን ጋር ተገናኝተዋል።"</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"እርስዎ ኢሜይሎችን፣ መተግበሪያዎችን እና ድር ጣቢያዎችንም ጨምሮ የአውታረ መረብ እንቅስቃሴዎን መከታተል ከሚችለው <xliff:g id="APPLICATION">%1$s</xliff:g> ጋር ተገናኝተዋል።"</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"እርስዎ ኢሜይሎችን፣ መተግበሪያዎችን እና ድር ጣቢያዎችንም ጨምሮ የግል የአውታረ መረብ እንቅስቃሴዎን መከታተል ከሚችለው <xliff:g id="APPLICATION">%1$s</xliff:g> ጋር ተገናኝተዋል።"</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"እርስዎ ኢሜይሎችን፣ መተግበሪያዎችን እና ድር ጣቢያዎችንም ጨምሮ የግል የአውታረ መረብ እንቅስቃሴዎን ከሚከታተለው ከ<xliff:g id="APPLICATION">%1$s</xliff:g> ጋር ተገናኝተዋል።"</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"የእርስዎ የስራ መገለጫ በ<xliff:g id="ORGANIZATION">%1$s</xliff:g> ነው የሚቀናበረው። ኢሜይሎችን፣ መተግበሪያዎችን እና ድር ጣቢያዎችን ጨምሮ የአውታረ መረብ እንቅስቃሴዎን መከታተል ከሚችለው <xliff:g id="APPLICATION">%2$s</xliff:g> ጋር ተገናጥቷል።\n\nተጨማሪ መረጃ ለማግኘት አስተዳዳሪዎን ያነጋግሩ።"</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"የስራ መገለጫዎ በ<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_disabled" msgid="7412534203633528135">"እራስዎ እስኪከፍቱት ድረስ መሣሪያ እንደተቆለፈ ይቆያል"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"ማሳወቂያዎችን ፈጥነው ያግኙ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 1a92e67..2de58fe 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -329,12 +329,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"تحذير <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"وضع العمل"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"إضاءة ليلية"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"‏الاتصال القريب المدى (NFC)"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"تم تعطيل الاتصال القريب المدى"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"تم تمكين الاتصال القريب المدى"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"ليست هناك عناصر تم استخدامها مؤخرًا"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"لقد محوتَ كل شيء"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"معلومات التطبيق"</string>
@@ -348,16 +345,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"تجاهل"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"فتح"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"تم الشحن"</string>
@@ -438,24 +430,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"‏قطع الاتصال بشبكة VPN"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"لقد اتصلت بتطبيق <xliff:g id="VPN_APP">%1$s</xliff:g>، الذي يمكن أن يراقب نشاط الشبكة، بما في ذلك رسائل البريد الإلكتروني والتطبيقات والمواقع الإلكترونية."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"‏فتح إعدادات الشبكة الظاهرية الخاصة (VPN)"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"شغَّل المشرف ميزة تسجيل بيانات الشبكة، والتي يتم من خلالها مراقبة حركة البيانات على جهازك.\n\nللحصول على المزيد من المعلومات، اتصل بالمشرف."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"‏لقد منحت تطبيقًا الإذن لإعداد اتصال شبكة ظاهرية خاصة (VPN).\n\nيمكن لهذا التطبيق مراقبة أنشطتك على الجهاز والشبكة، بما في ذلك الرسائل الإلكترونية والتطبيقات ومواقع الويب."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"تتم إدارة ملفك الشخصي للعمل بواسطة <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nويمكن للمشرف مراقبة نشاط الشبكة، بما في ذلك رسائل البريد الإلكتروني والتطبيقات والمواقع الإلكترونية.\n\nللحصول على المزيد من المعلومات، اتصل بالمشرف.\n\nوتجدر الإشارة إلى أنك متصل أيضًا بشبكة ظاهرية خاصة يمكن أن تراقب نشاط الشبكة."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"شبكة ظاهرية خاصة"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"أنت متصل بـ <xliff:g id="APPLICATION">%1$s</xliff:g>، الذي يمكنه مراقبة أنشطتك على الشبكة، بما في ذلك الرسائل الإلكترونية والتطبيقات ومواقع الويب."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"أنت متصل بـ <xliff:g id="APPLICATION">%1$s</xliff:g>، الذي يمكنه مراقبة أنشطتك الشخصية على الشبكة، بما في ذلك الرسائل الإلكترونية والتطبيقات ومواقع الويب."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"أنت متصل بـ <xliff:g id="APPLICATION">%1$s</xliff:g>، الذي يمكنه مراقبة أنشطتك الشخصية على الشبكة، بما في ذلك الرسائل الإلكترونية والتطبيقات ومواقع الويب."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"تتم إدارة ملفك الشخصي للعمل بواسطة <xliff:g id="ORGANIZATION">%1$s</xliff:g>، وهو متصل بتطبيق <xliff:g id="APPLICATION">%2$s</xliff:g>، الذي يمكن أن يراقب نشاطك على شبكة العمل، بما في ذلك رسائل البريد الإلكتروني والتطبيقات والمواقع الإلكترونية.\n\nللحصول على المزيد من المعلومات، اتصل بالمشرف."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"تتم إدارة ملفك الشخصي للعمل عن طريق <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_disabled" msgid="7412534203633528135">"سيظل الجهاز مقفلاً إلى أن يتم إلغاء قفله يدويًا"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"الحصول على الإشعارات بشكل أسرع"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 8950034..a60ee26 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -340,16 +340,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Üfüqi Böl"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Şaquli Böl"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Fərdi Böl"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Rədd edin"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Açın"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Ekranı yuxarıdan ayırın"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Ekranı soldan ayırın"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Ekranı sağdan ayırın"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Dolub"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 2313487f..4738057 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -323,12 +323,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Upozorenje za <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Režim rada"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Noćno svetlo"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC je onemogućen"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC je omogućen"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nema nedavnih stavki"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Obrisali ste sve"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacije o aplikaciji"</string>
@@ -342,16 +339,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podeli horizontalno"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podeli vertikalno"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Prilagođeno deljenje"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Odbaci"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Otvori"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Podeli ekran nagore"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Podeli ekran nalevo"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Podeli ekran nadesno"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Napunjena je"</string>
@@ -432,24 +424,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Prekini vezu sa VPN-om"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Uređajem upravlja <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> koristi <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> za upravljanje uređajem."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"Administrator može da nadgleda podešavanja, korporativni pristup, aplikacije, podatke povezane sa uređajem i informacije o lokaciji uređaja, kao i da upravlja njima."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Saznajte više"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Povezani ste sa aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>, koja može da nadgleda aktivnosti na mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Otvorite podešavanja VPN-a"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administrator je uključio evidentiranje mreže, koje prati saobraćaj na uređaju.\n\nKontaktirajte administratora za više informacija."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Dali ste dozvolu aplikaciji da podešava VPN vezu.\n\nTa aplikacija može da nadgleda aktivnosti na uređaju i mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> upravlja profilom za Work.\n\nAdministrator može da prati aktivnosti na mreži, uključujući imejlove, aplikacije i veb-sajtove.\n\nKontaktirajte administratora za više informacija.\n\nPovezani ste i sa VPN-om, koji može da prati aktivnosti na mreži."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Povezani ste sa aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može da nadgleda aktivnosti na mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Povezani ste sa aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može da nadgleda aktivnosti na ličnoj mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Povezani ste sa aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može da nadgleda aktivnosti na ličnoj mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> upravlja profilom za Work. On je povezan sa aplikacijom <xliff:g id="APPLICATION">%2$s</xliff:g>, koja može da prati aktivnosti na poslovnoj mreži, uključujući imejlove, aplikacije i veb-sajtove.\n\nKontaktirajte administratora za više informacija."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Profilom za Work upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Povezan je sa aplikacijom <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, koja može da nadgleda aktivnosti na poslovnoj mreži, uključujući imejlove, aplikacije i veb-sajtove.\n\nPovezani ste i sa aplikacijom <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, koja može da nadgleda aktivnosti na ličnoj mreži."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Uređaj će ostati zaključan dok ga ne otključate ručno"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Brže dobijajte obaveštenja"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 083342a..efbc1d2 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -327,12 +327,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Папярэджанне: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Рэжым працы"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Начная падсветка"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC адключаны"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC уключаны"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Няма нядаўніх элементаў"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Вы ачысцілі усё"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Звесткі аб праграме"</string>
@@ -346,16 +343,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Адхіліць"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Адкрыць"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Зараджаны"</string>
@@ -436,24 +428,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Адлучыць VPN"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Вы падключаны да праграмы <xliff:g id="VPN_APP">%1$s</xliff:g>, якая можа сачыць за вашай сеткавай дзейнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" ,"</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Адкрыйце налады VPN"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Ваш адміністратар уключыў вядзенне журнала сеткі, з дапамогай якога адсочваецца трафік на вашай прыладзе.\n\nДля атрымання дадатковай інфармацыі звярніцеся да адміністратара."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Вы далі праграме дазвол на наладжванне злучэння VPN.\n\nГэта праграма можа сачыць за актыўнасцю вашай прылады і вашай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"Вы падлучаны да праграмы <xliff:g id="APPLICATION">%1$s</xliff:g>, якая можа сачыць за вашай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Вы падлучаны да праграмы <xliff:g id="APPLICATION">%1$s</xliff:g>, якая сачыць за вашай асабістай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Вы падключаны да праграмы <xliff:g id="APPLICATION">%1$s</xliff:g>, якая можа сачыць за вашай асабістай сеткавай дзейнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Ваш працоўны профіль знаходзіцца пад кіраваннем <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Ён падключаны да праграмы <xliff:g id="APPLICATION">%2$s</xliff:g>, якая можа сачыць за вашай сеткавай дзейнасцю, уключаючы электронную пошту, праграмы і вэб-сайты.\n\nДля атрымання дадатковай інфармацыі звярніцеся да адміністратара."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Ваш працоўны профіль знаходзіцца пад кіраваннем <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_disabled" msgid="7412534203633528135">"Прылада будзе заставацца заблакіраванай, пакуль вы не разблакіруеце яе ўручную"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Атрымлівайце апавяшчэнні хутчэй"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 8382e38..8cb61d9 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Предупреждение: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Работен режим"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Нощно осветление"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"КБП"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"КБП е деактивирана"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"КБП е активирана"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Няма скорошни елементи"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Изчистихте всичко"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Информация за приложението"</string>
@@ -340,16 +337,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Отхвърляне"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Отваряне"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Заредена"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Прекратяване на връзката с VPN"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Установена е връзка с приложението <xliff:g id="VPN_APP">%1$s</xliff:g>, което може да наблюдава активността ви в мрежата, вкл. имейли, приложения и уебсайтове."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Отваряне на настройките за VPN"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Администраторът ви е включил функцията за регистриране на мрежовата активност, която следи трафика на устройството ви.\n\nЗа повече информация се свържете с администратора си."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Разрешихте на приложение да настрои връзка с виртуална частна мрежа (VPN).\n\nТова приложение може да наблюдава активността ви на устройството и в мрежата, включително имейли, приложения и уебсайтове."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"Установена е връзка с приложението <xliff:g id="APPLICATION">%1$s</xliff:g>, което може да наблюдава активността ви в мрежата, включително имейли, приложения и уебсайтове."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Установена е връзка с приложението <xliff:g id="APPLICATION">%1$s</xliff:g>, което може да наблюдава личната ви активност в мрежата, включително имейли, приложения и уебсайтове."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Установена е връзка с приложението <xliff:g id="APPLICATION">%1$s</xliff:g>, което може да наблюдава личната ви активност в мрежата, включително имейли, приложения и уебсайтове."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Служебният ви потребителски профил се управлява от <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Той е свързан с приложението <xliff:g id="APPLICATION">%2$s</xliff:g>, което може да наблюдава служебната ви активност в мрежата, включително имейли, приложения и уебсайтове.\n\nЗа повече информация се свържете с администратора си."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Служебният ви потребителски профил се управлява от <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_disabled" msgid="7412534203633528135">"Устройството ще остане заключено, докато не го отключите ръчно"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Получавайте известия по-бързо"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index f732279..ef0063f 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> সতর্কতা"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"কাজের মোড"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"নাইট লাইট"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC অক্ষম করা আছে"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC সক্ষম করা আছে"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"কোনো সাম্প্রতিক আইটেম নেই"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"আপনি সবকিছু সাফ করেছেন"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"অ্যাপ্লিকেশানের তথ্য"</string>
@@ -430,24 +427,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"VPN এর সংযোগ বিচ্ছিন্ন করুন"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"আপনি <xliff:g id="VPN_APP">%1$s</xliff:g> এ সংযুক্ত হয়েছেন, যা ইমেল, অ্যাপ এবং ওয়েবসাইটগুলি সহ আপনার নেটওয়ার্ক কার্যকলাপ নিরীক্ষণ করবে৷"</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"VPN সেটিংস খুলুন"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"আপনার প্রশাসক নেটওয়ার্ক লগিং চালু করেছেন, যা আপনার ডিভাইসের ট্রাফিক নিরীক্ষণ করে।\n\nআরো তথ্যের জন্য আপনার প্রশাসকের সাথে যোগাযোগ করুন।"</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"আপনি VPN সংযোগ সেট আপ করার জন্য একটি অ্যাপ্লিকেশানকে অনুমতি দিন৷\n\nএই অ্যাপ্লিকেশানটি ইমেল, অ্যাপ্লিকেশান ও ওয়েবসাইটগুলি সহ আপনার ডিভাইস এবং নেটওয়ার্কের কার্যকলাপ নিরীক্ষণ করতে পারে।"</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"আপনি <xliff:g id="APPLICATION">%1$s</xliff:g> -এ সংযুক্ত হয়েছেন, যা ইমেল, অ্যাপ্লিকেশান এবং ওয়েবসাইটগুলি সমেত আপনার নেটওয়ার্ক কার্যকলাপ নিরীক্ষণ করতে পারে৷"</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"আপনি <xliff:g id="APPLICATION">%1$s</xliff:g> -এ সংযুক্ত হয়েছেন, যা ইমেল, অ্যাপ্লিকেশান এবং ওয়েবসাইটগুলি সমেত আপনার ব্যক্তিগত নেটওয়ার্ক কার্যকলাপ নিরীক্ষণ করতে পারে৷"</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"আপনি <xliff:g id="APPLICATION">%1$s</xliff:g> এর সাথে সংযুক্ত হয়েছেন, যা ইমেল, অ্যাপ এবং ওয়েবসাইটগুলি সহ আপনার ব্যক্তিগত নেটওয়ার্কের কার্যকলাপ নিরীক্ষণ করবে৷"</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"আপনার কর্মস্থলের প্রোফাইলটি <xliff:g id="ORGANIZATION">%1$s</xliff:g> দ্বারা পরিচালিত হয়। সেটি <xliff:g id="APPLICATION">%2$s</xliff:g> এর সাথে সংযুক্ত যা আপনার ইমেল, অ্যাপ্স ও ওয়েবসাইট সহ কর্মস্থলের নেটওয়ার্ক কার্যকলাপ নিরীক্ষণ করতে পারে।\n\nআরো তথ্যের জন্য আপনার প্রশাসকের সঙ্গে যোগাযোগ করুন।"</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"<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_disabled" msgid="7412534203633528135">"আপনি নিজে আনলক না করা পর্যন্ত ডিভাইসটি লক হয়ে থাকবে"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"বিজ্ঞপ্তিগুলি আরো দ্রুত পান"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 948fccd..b694b4b 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -323,12 +323,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Upozorenje <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Poslovni režim"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Noćno svjetlo"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC je onemogućen"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC je omogućen"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nema nedavnih stavki"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Sve ste obrisali"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacije o aplikaciji"</string>
@@ -342,16 +339,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podjela po horizontali"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podjela po vertikali"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Prilagođena podjela"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Odbaci"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Otvori"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Podijeli ekran nagore"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Podijeli ekran nalijevo"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Podijeli ekran nadesno"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Napunjeno"</string>
@@ -432,24 +424,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Prekini VPN vezu"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Vašim uređajem upravlja aplikacija <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> koristi aplikaciju <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> za upravljanje vašim uređajem."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"Vaš administrator može pratiti postavke, korporativni pristup, aplikacije, podatke povezane s vašim uređajem i informacije o lokaciji vašeg uređaja."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Saznajte više"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Povezani ste s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>, koja može pratiti vašu aktivnost na mreži, uključujući e-poruke i web lokacije."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Postavke otvorene VPN mreže"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Vaš administrator je uključio zapisivanje na mreži, čime se prati saobraćaj na vašem uređaju.\n\nZa više informacija, obratite se administratoru."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Jednoj aplikaciji ste dali odobrenje da uspostavi VPN vezu.\n\nTa aplikacija može pratiti vašu aktivnost na uređaju i mreži, uključujući e-poštu, aplikacije i web-lokacije."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Vašim radnim profilom upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nVaš administrator može pratiti vašu aktivnost na radnoj mreži, uključujući e-poruke, aplikacije i web lokacije.\n\nZa više informacija, obratite se administratoru.\n\nPovezani ste i na VPN, koji može pratiti vašu aktivnost na mreži."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Povezani ste sa aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može pratiti vašu aktivnost na mreži, uključujući e-mailove, aplikacije i web-lokacije."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Povezani ste sa aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može pratiti vašu aktivnost na privatnoj mreži, uključujući e-mailove, aplikacije i web-lokacije."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Povezani ste na aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može pratiti vaše privatne aktivnosti na mreži, uključujući e-poštu, aplikacije i web stranice."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Vašim radnim profilom upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Povezan je s aplikacijom <xliff:g id="APPLICATION">%2$s</xliff:g>, koja može pratiti vašu aktivnost na radnoj mreži, uključujući e-poruke, aplikacije i web lokacije.\n\nZa više informacija, obratite se svom administratoru."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Profilom za posao upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Povezan je sa aplikacijom <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, koja može pratiti vašu aktivnost na radnoj mreži, uključujući e-poštu, aplikacije i web-lokacije.\n\nPovezani ste i sa aplikacijom <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, koja može pratiti vašu aktivnost na privatnoj mreži."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Uređaj će ostati zaključan dok ga ručno ne otključate"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Brže primaj obavještenja"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index fd10d12..fc61ab0 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advertiment: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Mode de feina"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Llum nocturna"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"L\'NFC està desactivada"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"L\'NFC està activada"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"No hi ha cap element recent"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Ho has esborrat tot"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informació de l\'aplicació"</string>
@@ -340,16 +337,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisió horitzontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisió vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisió personalitzada"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Ignora"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Obre"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Divideix la pantalla cap amunt"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Divideix la pantalla cap a l\'esquerra"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Divideix la pantalla cap a la dreta"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Desconnecta la VPN"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"<xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g> gestiona el teu dispositiu."</string>
     <string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> utilitza <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> per gestionar el teu dispositiu."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"L\'administrador pot supervisar i gestionar la configuració, l\'accés corporatiu, les aplicacions, la ubicació i les dades del dispositiu."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Més informació"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Estàs connectat a <xliff:g id="VPN_APP">%1$s</xliff:g>, que pot supervisar la teva activitat a la xarxa, com els correus electrònics, les aplicacions i els llocs web."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Obre la configuració de la VPN"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"L\'administrador ha activat el registre de xarxa, que supervisa el trànsit del teu dispositiu.\n\nPer obtenir més informació, contacta amb l\'administrador."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Has donat permís a una aplicació per configurar una connexió VPN.\n\nAquesta aplicació pot supervisar el dispositiu i l\'activitat a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> gestiona el teu perfil professional.\n\nL\'administrador pot supervisar la teva activitat a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web.\n\nPer obtenir més informació, contacta amb l\'administrador.\n\nA més, estàs connectat a una VPN, que també pot supervisar la teva activitat a la xarxa."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Estàs connectat a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pot supervisar la teva activitat a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Estàs connectat a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pot supervisar la teva activitat personal a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Estàs connectat a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pot supervisar la teva activitat personal a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> gestiona el teu perfil professional. Aquest perfil està connectat a <xliff:g id="APPLICATION">%2$s</xliff:g>, que pot supervisar la teva activitat professional a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web.\n\nPer obtenir més informació, contacta amb l\'administrador."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> gestiona el teu perfil professional. Aquest perfil està connectat a <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, que pot supervisar la teva activitat professional a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web.\n\nA més, estàs connectat a <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, que també pot supervisar la teva activitat personal a la xarxa."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"El dispositiu continuarà bloquejat fins que no el desbloquegis manualment."</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Obtén notificacions més ràpidament"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 51fb530..9cddbc3 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -346,16 +346,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Vodorovné rozdělení"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikální rozdělení"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Vlastní rozdělení"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Zrušit"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Otevřít"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Rozdělit obrazovku nahoru"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Rozdělit obrazovku vlevo"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Rozdělit obrazovku vpravo"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nabito"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 5c603a8..3b8783a 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -340,16 +340,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Opdel vandret"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Opdel lodret"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Opdel brugerdefineret"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Afvis"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Åbn"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Del skærm øverst"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Del skærm til venstre"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Del skærm til højre"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Opladet"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 8da6e9c..b2ad211 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -323,12 +323,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Warnung für <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Arbeitsmodus"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nachtlicht"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC ist deaktiviert"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ist aktiviert"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Keine kürzlich verwendeten Elemente"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Du hast alles gelöscht"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"App-Info"</string>
@@ -342,16 +339,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Geteilte Schaltfläche – horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Geteilte Schaltfläche – vertikal"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Geteilte Schaltfläche – benutzerdefiniert"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Schließen"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Öffnen"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Geteilten Bildschirm oben anzeigen"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Geteilten Bildschirm auf linker Seite anzeigen"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Geteilten Bildschirm auf der rechten Seite anzeigen"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Aufgeladen"</string>
@@ -432,24 +424,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"VPN-Verbindung trennen"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Dein Gerät wird von <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g> verwaltet."</string>
     <string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> verwaltet dein Gerät mit <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g>."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"Dein Administrator kann Einstellungen, Zugriffsrechte, Apps und Daten deines Geräts und dessen Standortinformationen überwachen und verwalten."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Weitere Informationen"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Du bist mit <xliff:g id="VPN_APP">%1$s</xliff:g> verbunden. Die VPN-App kann deine Netzwerkaktivitäten (E-Mails, Apps und Websites) erfassen."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"VPN-Einstellungen öffnen"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Dein Administrator hat die Netzwerkprotokollierung aktiviert. Damit wird der Verkehr auf deinem Gerät erfasst.\n\nWeitere Informationen erhältst du von deinem Administrator."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Du hast einer App gestattet, eine VPN-Verbindung einzurichten.\n\nDiese App kann dein Gerät und deine Netzwerkaktivitäten überwachen, einschließlich E-Mails, Apps und Websites."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Dein Arbeitsprofil wird von <xliff:g id="ORGANIZATION">%1$s</xliff:g> verwaltet.\n\nDein Administrator kann deine Netzwerkaktivitäten einschließlich E-Mails, Apps und Websites überwachen.\n\nWeitere Informationen erhältst du von deinem Administrator.\n\nAußerdem bist du mit einem VPN verbunden, das deine Netzwerkaktivitäten erfassen kann."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Du bist mit der App <xliff:g id="APPLICATION">%1$s</xliff:g> verbunden, die deine Netzwerkaktivität überwachen kann, einschließlich E-Mails, Apps und Websites."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Du bist mit der App <xliff:g id="APPLICATION">%1$s</xliff:g> verbunden, die deine persönliche Netzwerkaktivität überwachen kann, einschließlich E-Mails, Apps und Websites."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Du bist mit der App \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" verbunden. Diese kann deine persönlichen Netzwerkaktivitäten erfassen, einschließlich E-Mails, Apps und Websites."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Dein Arbeitsprofil wird von <xliff:g id="ORGANIZATION">%1$s</xliff:g> verwaltet. Es ist mit der App <xliff:g id="APPLICATION">%2$s</xliff:g> verbunden, die deine berufliche Netzwerkaktivitäten einschließlich E-Mails, Apps und Websites erfassen kann.\n\nWeitere Informationen erhältst du von deinem Administrator."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Dein Arbeitsprofil wird von <xliff:g id="ORGANIZATION">%1$s</xliff:g> verwaltet. Das Profil ist mit der App <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> verbunden, die deine geschäftliche Netzwerkaktivität überwachen kann, einschließlich E-Mails, Apps und Websites.\n\nDu bist außerdem mit der App <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> verbunden, die deine persönliche Netzwerkaktivität überwachen kann."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Das Gerät bleibt gesperrt, bis du es manuell entsperrst."</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Benachrichtigungen schneller erhalten"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index bc9d264..94965f1 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Προειδοποίηση για <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Λειτουργία εργασίας"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Νυχτερινός φωτισμός"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"Το NFC είναι απενεργοποιημένο"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"Το NFC είναι ενεργοποιημένο"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Δεν υπάρχουν πρόσφατα στοιχεία"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Έχει γίνει διαγραφή όλων των στοιχείων"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Πληροφορίες εφαρμογής"</string>
@@ -340,16 +337,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Παράβλεψη"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Άνοιγμα"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Φορτίστηκε"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Αποσύνδεση VPN"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Έχετε συνδεθεί στην εφαρμογή <xliff:g id="VPN_APP">%1$s</xliff:g>, η οποία μπορεί να παρακολουθεί τη δραστηριότητα δικτύου σας, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστοτόπων."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Άνοιγμα Ρυθμίσεων VPN"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Ο διαχειριστής σας έχει ενεργοποιήσει την καταγραφή δικτύου, η οποία παρακολουθεί την επισκεψιμότητα στη συσκευή σας.\n\nΓια περισσότερες πληροφορίες, επικοινωνήστε με τον διαχειριστή σας."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Παραχωρήσατε σε μια εφαρμογή άδεια για τη ρύθμιση σύνδεσης VPN.\n\nΑυτή η εφαρμογή μπορεί να παρακολουθεί τη δραστηριότητα της συσκευής και του δικτύου σας, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστότοπων."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"Έχετε συνδεθεί στην εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g>, η οποία μπορεί να παρακολουθεί τη δραστηριότητα του δικτύου σας, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστότοπων."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Έχετε συνδεθεί στην εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g>, η οποία μπορεί να παρακολουθεί τη δραστηριότητα του προσωπικού σας δικτύου, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστότοπων."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Έχετε συνδεθεί στην εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g>, η οποία μπορεί να παρακολουθεί τη δραστηριότητα του προσωπικού σας δικτύου, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστοτόπων."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Η διαχείριση του προφίλ εργασίας γίνεται από τον οργανισμό <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Είναι συνδεδεμένο στην εφαρμογή <xliff:g id="APPLICATION">%2$s</xliff:g>, η οποία μπορεί να παρακολουθεί τη δραστηριότητα του δικτύου εργασίας, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστότοπων.\n\nΓια περισσότερες πληροφορίες, επικοινωνήστε με το διαχειριστή."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Η διαχείριση του προφίλ εργασίας γίνεται από τον οργανισμό <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_disabled" msgid="7412534203633528135">"Η συσκευή θα παραμείνει κλειδωμένη έως ότου την ξεκλειδώσετε μη αυτόματα"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Λάβετε ειδοποιήσεις γρηγορότερα"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index a19ac0b..5f2beba 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -340,16 +340,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Customised"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Dismiss"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Open"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Split screen to the top"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Split screen to the left"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Split screen to the right"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Charged"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index a19ac0b..5f2beba 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -340,16 +340,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Customised"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Dismiss"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Open"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Split screen to the top"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Split screen to the left"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Split screen to the right"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Charged"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index a19ac0b..5f2beba 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -340,16 +340,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Customised"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Dismiss"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Open"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Split screen to the top"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Split screen to the left"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Split screen to the right"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Charged"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 7379347..beeb773 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -323,12 +323,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advertencia de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modo de trabajo"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Luz nocturna"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"La tecnología NFC está inhabilitada"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"La tecnología NFC está habilitada"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"No hay elementos recientes"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Todo borrado"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Información de la aplicación"</string>
@@ -342,16 +339,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"División horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"División vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"División personalizada"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Descartar"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Abrir"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Dividir pantalla en la parte superior"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Dividir pantalla a la izquierda"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Dividir pantalla a la derecha"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string>
@@ -432,24 +424,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Desconectar VPN"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"<xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g> administra tu dispositivo."</string>
     <string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> usa <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> para administrar tu dispositivo."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"Tu administrador controla la configuración, el acceso corporativo, las apps, los datos asociados a tu dispositivo y la información de ubicación."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Más información"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Estás conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>, que puede controlar la actividad de tu red, incluidos los correos electrónicos, las apps y los sitios web."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Abrir configuración de VPN"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Tu administrador activó el registro de red, que controla el tráfico en tu dispositivo.\n\nComunícate con él para obtener más información."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Permitiste que una aplicación configurara una conexión VPN.\n\nEsta aplicación puede supervisar la actividad de la red y del dispositivo, incluidos los correos electrónicos, las aplicaciones y los sitios web."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> administra tu perfil de trabajo.\n\nTu administrador puede controlar tu actividad en la red, como los correos electrónicos, las apps y los sitios web.\n\nComunícate con él para obtener más información.\n\nTambién estás conectado a una VPN, que puede controlar tu actividad en la red."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Tienes conexión a la aplicación <xliff:g id="APPLICATION">%1$s</xliff:g>, que puede supervisar la actividad de la red, incluidos los correos electrónicos, las aplicaciones y los sitios web."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Tienes conexión a la aplicación <xliff:g id="APPLICATION">%1$s</xliff:g>, que puede supervisar la actividad de la red personal, incluidos los correos electrónicos, las aplicaciones y los sitios web."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Te conectaste a <xliff:g id="APPLICATION">%1$s</xliff:g>, que puede supervisar la actividad de tu red personal, incluidos los correos electrónicos, las apps y los sitios web."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> administra tu perfil de trabajo. Está conectado a <xliff:g id="APPLICATION">%2$s</xliff:g>, que puede controlar la actividad de tu red laboral, como los correos electrónicos, las apps y los sitios web.\n\nPara obtener más información, comunícate con tu administrador."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> administra tu perfil de trabajo. Tiene conexión a <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, que puede supervisar la actividad de tu red de trabajo, incluidos los correos electrónicos, las aplicaciones y los sitios web.\n\nTambién tienes conexión a <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, que puede supervisar la actividad de la red personal."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"El dispositivo permanecerá bloqueado hasta que lo desbloquees manualmente."</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Recibe notificaciones más rápido"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index ea1d08f..ea2d0b6 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -212,10 +212,10 @@
     <string name="accessibility_quick_settings_bluetooth_connected" msgid="4306637793614573659">"Bluetooth conectado."</string>
     <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="2730003763480934529">"Bluetooth desactivado."</string>
     <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="8722351798763206577">"Bluetooth activado."</string>
-    <string name="accessibility_quick_settings_location_off" msgid="5119080556976115520">"Informes de Ubicación desactivados."</string>
-    <string name="accessibility_quick_settings_location_on" msgid="5809937096590102036">"Informes de Ubicación activados."</string>
-    <string name="accessibility_quick_settings_location_changed_off" msgid="8526845571503387376">"Informes de Ubicación desactivados."</string>
-    <string name="accessibility_quick_settings_location_changed_on" msgid="339403053079338468">"Informes de Ubicación activados."</string>
+    <string name="accessibility_quick_settings_location_off" msgid="5119080556976115520">"Informes de ubicación desactivados."</string>
+    <string name="accessibility_quick_settings_location_on" msgid="5809937096590102036">"Informes de ubicación activados."</string>
+    <string name="accessibility_quick_settings_location_changed_off" msgid="8526845571503387376">"Informes de ubicación desactivados."</string>
+    <string name="accessibility_quick_settings_location_changed_on" msgid="339403053079338468">"Informes de ubicación activados."</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"La alarma sonará a la(s) <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_close" msgid="3115847794692516306">"Cerrar panel."</string>
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Más tiempo."</string>
@@ -323,12 +323,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advertencia de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modo de trabajo"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Luz nocturna"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"La conexión NFC está inhabilitada"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"La conexión NFC está habilitada"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"No hay elementos recientes"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Has rechazado todo"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Información de la aplicación"</string>
@@ -342,16 +339,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"División horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"División vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"División personalizada"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Descartar"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Abrir"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Dividir la pantalla en la parte superior"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Dividir la pantalla a la izquierda"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Dividir la pantalla a la derecha"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string>
@@ -432,24 +424,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Desconectar VPN"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Tu dispositivo está administrado por <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> utiliza <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> para administrar tu dispositivo."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"Tu administrador puede controlar y gestionar su configuración, acceso corporativo y aplicaciones, así como los datos y la ubicación del dispositivo."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Más información"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Te has conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>, que puede controlar tu actividad de red, como los correos electrónicos, las aplicaciones y los sitios web."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Abrir Ajustes de red VPN"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Tu administrador ha activado el registro de la red para supervisar el tráfico en tu dispositivo.\n\nPonte en contacto con él para obtener más información."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Has concedido permiso a una aplicación para configurar una conexión VPN.\n\nEsta aplicación puede controlar tu dispositivo y tu actividad de red, como correos electrónicos, aplicaciones y sitios web."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"El administrador de tu perfil de trabajo es <xliff:g id="ORGANIZATION">%1$s</xliff:g>,\n\n que puede supervisar tu actividad de red, como correos electrónicos, aplicaciones y sitios web.\n\nPara obtener más información, ponte en contacto con tu administrador.\n\nTambién estás conectado a una red VPN, que puede supervisar tu actividad de red."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Estás conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que puede controlar tu actividad de red, como correos electrónicos, aplicaciones y sitios web."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Estas conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que puede controlar tu actividad de red personal, como correos electrónicos, aplicaciones y sitios web."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Estas conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que puede controlar tu actividad de red personal, como correos electrónicos, aplicaciones y sitios web."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"El administrador de tu perfil de trabajo es <xliff:g id="ORGANIZATION">%1$s</xliff:g> y está conectado a <xliff:g id="APPLICATION">%2$s</xliff:g>, que puede supervisar tu actividad de red en el trabajo, como correos electrónicos, aplicaciones y sitios web.\n\nPara obtener más información, ponte en contacto con tu administrador."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"El administrador de tu perfil de trabajo es <xliff:g id="ORGANIZATION">%1$s</xliff:g> y está conectado a <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, que puede controlar tu actividad de red, como correos electrónicos, aplicaciones y sitios web.\n\nTú también estás conectado a <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, que puede controlar tu actividad de red personal."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"El dispositivo permanecerá bloqueado hasta que se desbloquee manualmente"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Recibe notificaciones más rápido"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index e6f03a1..01a3f7c 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -323,12 +323,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> hoiatus"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Töörežiim"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Öövalgus"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC on keelatud"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC on lubatud"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Hiljutisi üksusi pole"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Olete kõik ära kustutanud"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Rakenduste teave"</string>
@@ -342,16 +339,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horisontaalne poolitamine"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikaalne poolitamine"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Kohandatud poolitamine"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Loobu"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Ava"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Poolita ekraan üles"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Poolita ekraan vasakule"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Poolita ekraan paremale"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Laetud"</string>
@@ -432,24 +424,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Katkesta VPN-i ühendus"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Teie seadet haldab rakendus <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g>."</string>
     <string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"Organisatsioon <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> kasutab teie seadme haldamiseks rakendust <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g>."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"Administraator saab jälgida ja hallata teie seadmega seotud seadeid, ettevõtte juurdepääsu, rakendusi ja andmeid ning seadme asukohateavet."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Lisateave"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Olete ühendatud rakendusega <xliff:g id="VPN_APP">%1$s</xliff:g>, mis saab jälgida teie võrgutegevusi, sh meile, rakendusi ja veebisaite."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Ava VPN-i seaded"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Teie administraator on sisse lülitanud võrgu logimise funktsiooni, mis jälgib teie seadmes liiklust.\n\nLisateabe saamiseks võtke ühendust administraatoriga."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Andsite rakendusele loa VPN-i ühenduse seadistamiseks.\n\nSee rakendus võib jälgida teie seadet ja võrgutegevusi, sh meile, rakendusi ja veebisaite."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Teie tööprofiili haldab <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministraator saab jälgida teie töökoha võrgutegevusi, sh meile, rakendusi ja veebisaite.\n\nLisateabe saamiseks võtke ühendust administraatoriga.\n\nTeil on ühendus ka VPN-iga, mis saab teie võrgutegevusi jälgida."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Teie seade on ühendatud rakendusega <xliff:g id="APPLICATION">%1$s</xliff:g>, mis võib jälgida teie võrgutegevusi, sh meile, rakendusi ja veebisaite."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Teie seade on ühendatud rakendusega <xliff:g id="APPLICATION">%1$s</xliff:g>, mis võib jälgida teie isiklikke võrgutegevusi, sh meile, rakendusi ja veebisaite."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Olete ühendatud rakendusega <xliff:g id="APPLICATION">%1$s</xliff:g>, mis võib jälgida teie isiklikke võrgutegevusi, sh meile, rakendusi ja veebisaite."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Teie tööprofiili haldab <xliff:g id="ORGANIZATION">%1$s</xliff:g>. See on ühendatud rakendusega <xliff:g id="APPLICATION">%2$s</xliff:g>, mis võib jälgida teie töökoha võrgutegevusi, sh meile, rakendusi ja veebisaite.\n\nLisateabe saamiseks võtke ühendust administraatoriga."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Teie tööprofiili haldab organisatsioon <xliff:g id="ORGANIZATION">%1$s</xliff:g>. See on ühendatud rakendusega <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, mis võib jälgida teie töökoha võrgutegevusi, sh meile, rakendusi ja veebisaite.\n\nTeie seade on ühendatud ka rakendusega <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, mis võib jälgida teie isiklikke võrgutegevusi."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Seade jääb lukku, kuni selle käsitsi avate"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Saate märguandeid kiiremini"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index eff5931..9d48236 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -323,12 +323,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Abisua: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Lan modua"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Gaueko argia"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"Desgaituta dago NFC"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"Gaituta dago NFC"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Ez dago azkenaldi honetako ezer"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Dena garbitu duzu"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Aplikazioaren informazioa"</string>
@@ -342,16 +339,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Baztertu"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Ireki"</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-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Kargatuta"</string>
@@ -432,24 +424,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Deskonektatu VPN sarea"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"<xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g> aplikazioak kudeatzen du gailu hau."</string>
     <string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> erakundeak <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> erabiltzen du gailua kudeatzeko."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"Gailuko ezarpenak, enpresa-sarbidea, aplikazioak eta datuak gainbegira eta kudea ditzake administratzaileak, baita gailuaren kokapen-informazioa ere."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Informazio gehiago"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"<xliff:g id="VPN_APP">%1$s</xliff:g> aplikaziora konektatuta zaude eta hark sareko jarduerak gainbegira ditzake, mezu elektronikoak, aplikazioak eta webguneak barne."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Ireki VPN ezarpenak"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administratzaileak sare-erregistroak aktibatu ditu; horrela, zure gailuko trafikoa gainbegira dezake.\n\nInformazio gehiago lortzeko, jarri administratzailearekin harremanetan."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Aplikazio bati VPN konexio bat konfiguratzeko baimena eman diozu.\n\nAplikazio horrek gailuko eta sareko jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webguneak barne."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> erakundeak kudeatzen du zure laneko profila.\n\nAdministratzaileak sareko jarduerak kontrola diezazkizuke, besteak beste, posta elektronikoa, aplikazioak eta webguneak.\n\nInformazio gehiago lortzeko, jarri administratzailearekin harremanetan.\n\nHorrez gain, VPN batera zaude konektatuta, eta hark ere kontrola ditzake zure sareko jarduerak."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN konexioa"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"<xliff:g id="APPLICATION">%1$s</xliff:g> aplikaziora konektatuta zaude. Aplikazio horrek sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webguneak barne."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"<xliff:g id="APPLICATION">%1$s</xliff:g> aplikaziora konektatuta zaude. Aplikazio horrek sarean egiten dituzun jarduera pertsonalak kontrola ditzake, mezu elektronikoak, aplikazioak eta webguneak barne."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"<xliff:g id="APPLICATION">%1$s</xliff:g> aplikaziora konektatuta zaude. Aplikazio horrek sarean egiten dituzun jarduera pertsonalak kontrola ditzake, mezu elektronikoak, aplikazioak eta webguneak barne."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> erakundeak kudeatzen du zure laneko profila. Erakundea <xliff:g id="APPLICATION">%2$s</xliff:g> aplikaziora dago konektatuta, bera arduratzen baita laneko sareko jarduerak kontrolatzeaz, besteak beste, posta elektronikoa, aplikazioak eta webguneak.\n\nInformazio gehiago lortzeko, jarri administratzailearekin harremanetan."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> da laneko profilaren kudeatzailea, eta profila <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> aplikaziora konektatuta dago. Aplikazio horrek sarean egiten dituzun laneko jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webguneak barne.\n\nHorrez gain, sarean egiten dituzun jarduera pertsonalak kontrola ditzakeen <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> aplikaziora konektatuta zaude."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Gailua blokeatuta egongo da eskuz desblokeatu arte"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Eskuratu jakinarazpenak azkarrago"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 8cba6a9..d65b218 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -340,16 +340,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"نپذیرفتن"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"باز کردن"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"شارژ کامل شد"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 89178d6..dda508f 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -340,16 +340,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Vaakasuuntainen jako"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Pystysuuntainen jako"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Muokattu jako"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Hylkää"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Avaa"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Jaa näyttö ylös"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Jaa näyttö vasemmalle"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Jaa näyttö oikealle"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Ladattu"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index a26f155..0790fb4 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -342,16 +342,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Séparation horizontale"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Séparation verticale"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Séparation personnalisée"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Fermer"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Ouvrir"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Écran partagé dans le haut"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Écran partagé à la gauche"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Écran partagé à la droite"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Chargée"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 4090aed..f693c98 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -342,16 +342,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Séparation horizontale"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Séparation verticale"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Séparation personnalisée"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Ignorer"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Ouvrir"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Partager l\'écran en haut"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Partager l\'écran sur la gauche"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Partager l\'écran sur la droite"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Chargé"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 881d967..fda9ffe 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -342,16 +342,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Dividir en horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Dividir en vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Dividir de xeito personalizado"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Ignorar"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Abrir"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Dividir pantalla na parte superior"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Dividir pantalla á esquerda"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Dividir pantalla á dereita"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Cargada"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 1b9ea1d..540ab16 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ચેતવણી"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"કાર્ય મોડ"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"રાત્રિ પ્રકાશ"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC અક્ષમ કરેલ છે"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC સક્ષમ કરેલ છે"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"કોઇ તાજેતરની આઇટમ્સ નથી"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"તમે બધું સાફ કર્યું"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"ઍપ્લિકેશન માહિતી"</string>
@@ -430,24 +427,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"VPN ડિસ્કનેક્ટ કરો"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"તમે <xliff:g id="VPN_APP">%1$s</xliff:g> સાથે કનેક્ટ થયાં છો, જે ઇમેઇલ્સ, ઍપ્લિકેશનો અને વેબસાઇટ્સ સહિત તમારી નેટવર્ક પ્રવૃત્તિને મૉનિટર કરી શકે છે."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"VPN સેટિંગ્સ ખોલો"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"તમારા વ્યવસ્થાપકે નેટવર્ક લૉગિંગ ચાલુ કર્યુ છે, જે તમારા ઉપકરણ પર ટ્રાફિકનું નિરીક્ષણ કરે છે.\n\nવધુ માહિતી માટે, તમારા વ્યવસ્થાપકનો સંપર્ક કરો."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"તમે VPN કનેક્શન સેટ કરવા માટે ઍપ્લિકેશન પરવાનગી આપી.\n\nઆ ઍપ્લિકેશન ઇમેઇલ્સ, ઍપ્લિકેશનો અને વેબસાઇટ્સ સહિત તમારા ઉપકરણ અને નેટવર્ક પ્રવૃત્તિને મૉનિટર કરી શકે છે."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"તમે <xliff:g id="APPLICATION">%1$s</xliff:g> સાથે કનેક્ટ થયાં છો, જે ઇમેઇલ્સ, ઍપ્લિકેશનો અને વેબસાઇટ્સ સહિતની તમારી નેટવર્ક પ્રવૃત્તિને મૉનિટર કરી શકે છે."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"તમે <xliff:g id="APPLICATION">%1$s</xliff:g> સાથે કનેક્ટ થયાં છો, જે ઇમેઇલ્સ, ઍપ્લિકેશનો અને વેબસાઇટ્સ સહિતની તમારી વ્યક્તિગત નેટવર્ક પ્રવૃત્તિને મૉનિટર કરી શકે છે."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"તમે <xliff:g id="APPLICATION">%1$s</xliff:g> સાથે કનેક્ટ થયાં છો, જે ઇમેઇલ્સ, ઍપ્લિકેશનો અને વેબસાઇટ્સ સહિત તમારી વ્યક્તિગત નેટવર્ક પ્રવૃત્તિને મૉનિટર કરી શકે છે."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"તમારી કાર્ય પ્રોફાઇલનું સંચાલન <xliff:g id="ORGANIZATION">%1$s</xliff:g> દ્વારા કરવામાં આવે છે. તેને <xliff:g id="APPLICATION">%2$s</xliff:g> સાથે કનેક્ટ કરેલ છે, જે ઇમેઇલ, ઍપ્લિકેશનો અને વેબસાઇટો સહિતની તમારી કાર્ય નેટવર્ક પ્રવૃત્તિનું નિરીક્ષણ કરી શકે છે. \n\nવધુ માહિતી માટે, તમારા વ્યવસ્થાપકનો સંપર્ક કરો."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"તમારી કાર્ય પ્રોફાઇલ <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_disabled" msgid="7412534203633528135">"તમે ઉપકરણને મેન્યુઅલી અનલૉક કરશો નહીં ત્યાં સુધી તે લૉક રહેશે"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"વધુ ઝડપથી સૂચનાઓ મેળવો"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 84dc2c4..3308662 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> चेतावनी"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"कार्य मोड"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"नाइट लाइट"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC बंद है"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC चालू है"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"हाल ही का कोई आइटम नहीं"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"आपने सब कुछ साफ़ कर दिया है"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"एप्‍लिकेशन जानकारी"</string>
@@ -340,16 +337,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"खारिज करें"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"खुला"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"चार्ज हो गई है"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"VPN डिस्‍कनेक्‍ट करें"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"आप <xliff:g id="VPN_APP">%1$s</xliff:g> से कनेक्‍ट हैं, जो ईमेल, ऐप्लिकेशन और वेबसाइट सहित आपकी नेटवर्क गतिविधि को मॉनिटर कर सकता है."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"VPN सेटिंग खोलें"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"आपके व्‍यवस्‍थापक ने नेटवर्क लॉग करना चालू कर दिया है, जो आपके डिवाइस पर ट्रैफ़िक की निगरानी करता है.\n\nअधिक जानकारी के लिए अपने व्‍यवस्‍थापक से संपर्क करें."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"आपने किसी ऐप को VPN कनेक्‍शन सेट करने की अनुमति दी है.\n\nयह ऐप ईमेल, ऐप्‍स और सुरक्षित वेबसाइटों सहित आपके डिवाइस और नेटवर्क की गतिविधि की निगरानी कर सकता है."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> से कनेक्‍ट हैं, जो ईमेल, ऐप्‍स और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> से कनेक्‍ट हैं, जो ईमेल, ऐप्‍स और वेबसाइटों सहित आपकी व्‍यक्‍तिगत नेटवर्क गतिविधि की निगरानी कर सकता है."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> से कनेक्‍ट हैं, जो ईमेल, ऐप्लिकेशन और वेबसाइट सहित आपकी व्‍यक्‍तिगत नेटवर्क गतिविधि को मॉनिटर कर सकता है."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> आपकी कार्य प्रोफ़ाइल को प्रबंधित करता है. वह ऐसे <xliff:g id="APPLICATION">%2$s</xliff:g> से कनेक्‍ट है, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी कार्य नेटवर्क गतिविधि की निगरानी कर सकता है.\n\nअधिक जानकारी के लिए अपने व्यवस्थापक से संपर्क करें."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"आपकी कार्य प्रोफ़ाइल <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_disabled" msgid="7412534203633528135">"जब तक कि आप मैन्‍युअल रूप से अनलॉक नहीं करते तब तक डिवाइस लॉक रहेगा"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"सूचनाएं अधिक तेज़ी से प्राप्त करें"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 8d626c8..6a2ce8c 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -323,12 +323,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Upozorenje <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Način rada"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Noćno svjetlo"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC je onemogućen"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC je omogućen"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nema nedavnih stavki"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Izbrisali ste sve"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacije o aplikaciji"</string>
@@ -342,16 +339,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podijeli vodoravno"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podijeli okomito"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Podijeli prilagođeno"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Odbaci"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Otvori"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Podijeli zaslon na vrhu"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Podijeli zaslon slijeva"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Podijeli zaslon zdesna"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Napunjeno"</string>
@@ -432,24 +424,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Prekini vezu s VPN-om"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Vašim uređajem upravlja aplikacija <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> upotrebljava aplikaciju <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> za upravljanje vašim uređajem."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"Administrator može nadzirati postavke, korporacijski pristup, aplikacije, podatke o uređaju i lokaciji uređaja te upravljati njima"</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Saznajte više"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Povezani ste s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g> koja može nadzirati vašu aktivnost na mreži, uključujući e-poštu, aplikacije i web-lokacije."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Otvorite postavke VPN-a"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administrator je uključio mrežni zapisnik koji prati promet na vašem uređaju.\n\nViše informacija možete saznati od administratora."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Dali ste dopuštenje aplikaciji za postavljanje VPN veze.\n\nTa aplikacija može nadzirati vašu aktivnost na uređaju i mreži, uključujući e-poštu, aplikacije i web-lokacije."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Vašim radnim profilom upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nVaš administrator može nadzirati vašu mrežnu aktivnost, uključujući e-poštu, aplikacije i web-lokacije.\n\nViše informacija možete saznati od administratora.\n\nPovezani ste i s VPN-om koji može nadzirati vašu mrežnu aktivnost."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Povezani ste s aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g> koja može nadzirati vašu aktivnost na mreži, uključujući e-poštu, aplikacije i web-lokacije."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Povezani ste s aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g> koja može nadzirati vašu osobnu aktivnost na mreži, uključujući e-poštu, aplikacije i web-lokacije."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Povezani ste s aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g> koja može nadzirati vašu osobnu aktivnost na mreži, uključujući e-poštu, aplikacije i web-lokacije."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Vašim radnim profilom upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profil je povezan s aplikacijom <xliff:g id="APPLICATION">%2$s</xliff:g> koja može nadzirati vašu poslovnu aktivnost na mreži, uključujući e-poštu, aplikacije i web-lokacije.\n\nViše informacija možete saznati od administratora."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Vašim poslovnim profilom upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Povezan je s aplikacijom <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> koja može nadzirati vašu poslovnu aktivnost na mreži, uključujući e-poštu, aplikacije i web-lokacije.\n\nPovezani ste i s aplikacijom <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> koja može nadzirati vašu osobnu aktivnost na mreži."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Uređaj će ostati zaključan dok ga ručno ne otključate"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Primajte obavijesti brže"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index b18d594..334427f 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Figyelem! <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Munka mód"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Éjszakai fény"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"Az NFC ki van kapcsolva"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"Az NFC be van kapcsolva"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nincsenek mostanában használt elemek"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Mindent törölt"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Az alkalmazás adatai"</string>
@@ -340,16 +337,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Osztott vízszintes"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Osztott függőleges"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Osztott egyéni"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Elvetés"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Megnyitás"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Osztott képernyő felülre"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Osztott képernyő balra"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Osztott képernyő jobbra"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Feltöltve"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"VPN-kapcsolat bontása"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Az eszközt a(z) <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g> kezeli."</string>
     <string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"A(z) <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> a(z) <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> alkalmazást használja az eszközkezeléshez."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"A rendszergazda felügyelheti és kezelheti az eszköz beállításait, vállalatszintű hozzáférését, alkalmazásait, adatait és helyadatait."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"További információ"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Ön kapcsolódik ehhez: <xliff:g id="VPN_APP">%1$s</xliff:g>, amely figyelheti hálózati tevékenységét, köztük a levelezést, az alkalmazás- és webhelyhasználatot."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"VPN-beállítások megnyitása"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"A rendszergazda bekapcsolta az eszköz forgalmát figyelő hálózati naplózást.\n\nHa további információra van szüksége, forduljon a rendszergazdához."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Engedélyezte egy alkalmazásnak, hogy VPN-kapcsolatot létesítsen.\n\nEz az alkalmazás (az e-mailekre, alkalmazásokra és a webhelyekre is kiterjedően) figyelemmel kísérheti az Ön eszközét és hálózati tevékenységét."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Munkaprofilját a(z) <xliff:g id="ORGANIZATION">%1$s</xliff:g> kezeli.\n\nA rendszergazda felügyelheti hálózati tevékenységét, köztük az e-maileket, az alkalmazásokat és a webhelyeket.\n\nHa további információra van szüksége, forduljon a rendszergazdához.\n\nVPN-hez is kapcsolódik, amely szintén felügyelheti hálózati tevékenységét."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Csatlakoztatta a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazást, amely figyelheti hálózati tevékenységét, beleértve az e-maileket, az alkalmazásokat és a webhelyeket."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Csatlakoztatta a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazást, amely figyelheti személyes hálózati tevékenységét, beleértve az e-maileket, az alkalmazásokat és a webhelyeket."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Ön a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazáshoz csatlakozik, amely figyelheti személyes hálózati tevékenységét, beleértve az e-maileket, alkalmazásokat és webhelyeket."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Munkaprofilját a(z) <xliff:g id="ORGANIZATION">%1$s</xliff:g> kezeli. Össze van kapcsolva a(z) <xliff:g id="APPLICATION">%2$s</xliff:g> alkalmazással, amely felügyelheti az Ön munkahelyi hálózati tevékenységét, beleértve az e-maileket, az alkalmazásokat és a webhelyeket.\n\nHa további információra van szüksége, forduljon a rendszergazdához."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Munkaprofilját a(z) <xliff:g id="ORGANIZATION">%1$s</xliff:g> felügyeli. Csatlakoztatva van hozzá a(z) <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> alkalmazás, amely figyelheti az Ön hálózati tevékenységét, beleértve az e-maileket, az alkalmazásokat és a webhelyeket.\n\nCsatlakoztatta továbbá a(z) <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> alkalmazást, amely szintén figyelemmel kísérheti személyes hálózati tevékenységét."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Az eszköz addig zárolva marad, amíg kézileg fel nem oldja"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Gyorsabban megkaphatja az értesítéseket"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index fa7cbe1..ef351bb9 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> զգուշացում"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Աշխատանքային ռեժիմ"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Գիշերային լույս"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC-ն անջատված է"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC-ն միացված է"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Վերջին տարրեր չկան"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Դուք ջնջել եք ամենը"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Հավելվածի մասին"</string>
@@ -340,16 +337,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Փակել"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Բացել"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Լիցքավորված է"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Անջատել VPN-ը"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Դուք կապակցված եք <xliff:g id="VPN_APP">%1$s</xliff:g> հավելվածին, որը կարող է վերահսկել ձեր ցանցային գործողությունը, այդ թվում նաև էլփոստը, հավելվածները և կայքերը:"</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Բացել VPN-ի կարգավորումները"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Ձեր ադմինիստրատորը միացրել է ցանցային իրադարձությունների գրանցումը, որը վերահսկում է ձեր սարքի թրաֆիկը։\n\nԼրացուցիչ տեղեկություններ ստանալու համար դիմեք ձեր ադմինիստրատորին։"</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Ինչ-որ հավելվածի թույլ եք տվել հաստատել VPN կապակցում:\n\nԱյդ հավելվածը կարող է վերահսկել ձեր սարքի և ցանցի գործունեությունը, այդ թվում նաև էլփոստի հաշիվները, հավելվածները և կայքերը:"</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"Դուք կապակցված եք <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածին, որը կարող է վերահսկել ձեր ցանցի գործունեությունը, այդ թվում նաև էլփոստի հաշիվները, հավելվածները և կայքերը:"</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Դուք կապակցված եք <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածին, որը կարող է վերահսկել անձնական ցանցում կատարած ձեր գործողությունները, այդ թվում նաև էլփոստի հաշիվները, հավելվածները և կայքերը:"</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Դուք կապակցված եք <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածին, որը կարող է վերահսկել անձնական ցանցում կատարած ձեր գործողությունները, այդ թվում նաև էլփոստի հաշիվները, հավելվածները և կայքերը:"</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Ձեր աշխատանքային պրոֆիլի կառավարիչն է <xliff:g id="ORGANIZATION">%1$s</xliff:g> կազմակերպությունը։ Այն կապակցված է <xliff:g id="APPLICATION">%2$s</xliff:g> հավելվածին, որը կարող է վերահսկել ձեր ցանցային գործունեությունը, այդ թվում նաև էլփոստը, հավելվածները և կայքերը։\n\nԼրացուցիչ տեղեկությունների համար դիմեք ադմինիստրատորին:"</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Աշխատանքային պրոֆիլի կառավարիչն է՝ <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_disabled" msgid="7412534203633528135">"Սարքը կմնա արգելափակված՝ մինչև ձեռքով չբացեք"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Ավելի արագ ստացեք ծանուցումները"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index d2b7a81..6ace014 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Peringatan <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Mode kerja"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Cahaya Malam"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC dinonaktifkan"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC diaktifkan"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Tidak ada item baru-baru ini"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Anda sudah menghapus semua"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Info Aplikasi"</string>
@@ -340,16 +337,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Pisahkan Horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Pisahkan Vertikal"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Pisahkan Khusus"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Tutup"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Buka"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Pisahkan layar ke atas"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Pisahkan layar ke kiri"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Pisahkan layar ke kanan"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Terisi"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Putuskan sambungan VPN"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Perangkat dikelola oleh <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> menggunakan <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> untuk mengelola perangkat Anda."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"Admin dapat memantau dan mengelola setelan, akses perusahaan, aplikasi, data terkait perangkat, dan informasi lokasi perangkat."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Pelajari lebih lanjut"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Anda tersambung ke <xliff:g id="VPN_APP">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Buka Setelan VPN"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Admin telah mengaktifkan pencatatan log jaringan, yang memantau traffic di perangkat.\n\nUntuk informasi selengkapnya, hubungi admin."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Anda memberikan izin kepada aplikasi untuk menyiapkan sambungan VPN.\n\nAplikasi ini ini dapat memantau aktivitas perangkat dan jaringan, termasuk email, aplikasi, dan situs web."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Profil kerja dikelola oleh <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdmin dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web.\n\nUntuk informasi selengkapnya, hubungi admin.\n\nAnda juga tersambung ke VPN, yang dapat memantau aktivitas jaringan."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Anda tersambung ke <xliff:g id="APPLICATION">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Anda tersambung ke <xliff:g id="APPLICATION">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan pribadi, termasuk email, aplikasi, dan situs web."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Anda tersambung ke <xliff:g id="APPLICATION">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan pribadi, termasuk email, aplikasi, dan situs web.."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Profil kerja dikelola oleh <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Profil ini terhubung ke <xliff:g id="APPLICATION">%2$s</xliff:g>, yang dapat memantau aktivitas jaringan kerja, termasuk email, aplikasi, dan situs web.\n\nUntuk informasi selengkapnya, hubungi admin."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Profil kerja dikelola oleh <xliff:g id="ORGANIZATION">%1$s</xliff:g> dan tersambung ke <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, yang dapat memantau aktivitas jaringan kerja, termasuk email, aplikasi, dan situs web.\n\nAnda juga tersambung ke <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, yang dapat memantau aktivitas jaringan pribadi."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Perangkat akan tetap terkunci hingga Anda membukanya secara manual"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Dapatkan pemberitahuan lebih cepat"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 28ccdf5..8538305 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> viðvörun"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Vinnustilling"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Næturljós"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"Slökkt á NFC"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"Kveikt á NFC"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Engin nýleg atriði"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Þú hefur hreinsað allt"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Forritsupplýsingar"</string>
@@ -340,16 +337,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Lárétt skipting"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Lóðrétt skipting"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Sérsniðin skipting"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Hunsa"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Opna"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Skipta skjá að ofanverðu"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Skipta skjá til vinstri"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Skipta skjá til hægri"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Fullhlaðin"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Aftengja VPN-net"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Þessu tæki er stýrt af <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> notar <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> til að stýra tækinu þínu."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"Kerfisstjóri getur fylgst með og stjórnað stillingum, fyrirtækjaaðgangi, forritum, gögnum tengdum tækinu og staðsetningu tækisins."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Frekari upplýsingar"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Þú ert með tengingu við <xliff:g id="VPN_APP">%1$s</xliff:g>, sem getur fylgst með netnotkun þinni, þ. á m. tölvupósti, forritum og vefsvæðum."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Opna VPN-stillingar"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Kerfisstjóri hefur kveikt á eftirliti netkerfa, sem fylgist með netumferð á tækinu þínu.\n\nHafðu samband við kerfisstjóra til að fá frekari upplýsingar."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Þú veittir forriti heimild til að koma á VPN-tengingu.\n\nÞetta forrit getur fylgst með virkni þinni í tækinu og á netinu, þar á meðal tölvupósti, forritum og vefsvæðum."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> stýrir vinnusniðinu þínu.\n\nKerfisstjórinn getur fylgst með virkni þinni á netinu, þ.m.t. tölvupósti, forritum og vefsvæðum.\n\nHafðu samband við kerfisstjórann til að fá frekari upplýsingar.\n\nÞú ert einnig með VPN-tengingu, sem getur fylgst með virkni þinni á netinu."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Þú ert með tengingu við <xliff:g id="APPLICATION">%1$s</xliff:g>, sem getur fylgst með netnotkun þinni, þ. á m. tölvupósti, forritum og vefsvæðum."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Þú ert með tengingu við <xliff:g id="APPLICATION">%1$s</xliff:g>, sem getur fylgst með persónulegri netnotkun þinni, þ. á m. tölvupósti, forritum og vefsvæðum."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Þú ert með tengingu við <xliff:g id="APPLICATION">%1$s</xliff:g>, sem getur fylgst með persónulegri netnotkun þinni, þ. á m. tölvupósti, forritum og vefsvæðum."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> stýrir vinnusniðinu þínu. Það er tengt við <xliff:g id="APPLICATION">%2$s</xliff:g>, sem getur fylgst með netvirkni þinni í vinnunni, þar á meðal tölvupósti, forritum og vefsvæðum.\n\nHafðu samband við kerfisstjóra til að fá frekari upplýsingar."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Vinnusniðinu þínu er stjórnað af <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Það er tengt <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, sem getur fylgst með vinnutengdri netnotkun þinni, þar á meðal tölvupósti, forritum og vefsvæðum.\n\nÞú ert einnig með tengingu við <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, sem getur fylgst með persónulegri netnotkun þinni."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Tækið verður læst þar til þú opnar það handvirkt"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Fáðu tilkynningar hraðar"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 515f77f..3273784 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -323,12 +323,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Avviso <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modalità Lavoro"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Luminosità notturna"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC non attiva"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC attiva"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nessun elemento recente"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Hai cancellato tutto"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informazioni sull\'applicazione"</string>
@@ -342,16 +339,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisione in orizzontale"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisione in verticale"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisione personalizzata"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Ignora"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Apri"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Schermo diviso in alto"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Schermo diviso a sinistra"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Schermo diviso a destra"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carica"</string>
@@ -432,24 +424,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Scollega VPN"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Il dispositivo è gestito dall\'app <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> utilizza l\'app <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> per gestire il dispositivo."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"L\'amministratore può monitorare e gestire impostazioni, accesso aziendale, app, dati associati al dispositivo e informazioni sulla posizione del dispositivo."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Ulteriori informazioni"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Sei connesso a <xliff:g id="VPN_APP">%1$s</xliff:g>, che consente di monitorare le attività di rete, inclusi siti web, email e app."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Apri impostazioni VPN"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"L\'amministratore ha attivato i log di rete, che consentono di monitorare il traffico sul dispositivo.\n\nPer ulteriori informazioni, contatta l\'amministratore."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Hai autorizzato l\'app a configurare una connessione VPN.\n\nQuesta app può monitorare il tuo dispositivo e l\'attività di rete, inclusi email, app e siti web."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Il tuo profilo di lavoro è gestito da <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nL\'amministratore può monitorare la tua attività di rete, inclusi siti web, email e app.\n\nPer ulteriori informazioni, contatta l\'amministratore.\n\nSei inoltre connesso a una VPN, da cui è possibile monitorare la tua attività di rete."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Sei connesso a <xliff:g id="APPLICATION">%1$s</xliff:g>, da cui è possibile monitorare la tua attività di rete, inclusi email, app e siti web."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Sei connesso a <xliff:g id="APPLICATION">%1$s</xliff:g>, da cui è possibile monitorare la tua attività di rete personale, inclusi email, app e siti web."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Sei collegato a <xliff:g id="APPLICATION">%1$s</xliff:g>, che consente di monitorare la tua attività di rete personale, inclusi siti web, email e app."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Il tuo profilo di lavoro è gestito da <xliff:g id="ORGANIZATION">%1$s</xliff:g>. È connesso a <xliff:g id="APPLICATION">%2$s</xliff:g>, da cui è possibile monitorare la tua attività di rete lavorativa, inclusi siti web, email e app.\n\nPer ulteriori informazioni, contatta l\'amministratore."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Il tuo profilo di lavoro è gestito da <xliff:g id="ORGANIZATION">%1$s</xliff:g>. È connesso a <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, da cui è possibile monitorare la tua attività di rete lavorativa, inclusi email, app e siti web.\n\nSei connesso anche a <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, da cui è possibile monitorare la tua attività di rete personale."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Il dispositivo resterà bloccato fino allo sblocco manuale"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Ricevi notifiche più velocemente"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index a32fbf6..c33c536 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -325,12 +325,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"אזהרה - <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"מצב עבודה"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"תאורת לילה"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"‏NFC מושבת"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"‏NFC מופעל"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"אין פריטים אחרונים"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"מחקת הכול"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"מידע על האפליקציה"</string>
@@ -344,16 +341,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"סגור"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"פתח"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"טעון"</string>
@@ -434,24 +426,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"‏נתק את ה-VPN"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"אתה מחובר לאפליקציה <xliff:g id="VPN_APP">%1$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת, כולל הודעות אימייל, אפליקציות ואתרים."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"‏פתח את הגדרות ה-VPN"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"מנהל המערכת הפעיל את תכונת רישום התנועה ברשת, שמנטרת את תנועת הנתונים במכשיר.\n\nלמידע נוסף, צור קשר עם מנהל המערכת."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"‏נתת לאפליקציה כלשהי הרשאה להגדיר חיבור ‏VPN‏.\n\nהאפליקציה הזו יכולה לעקוב אחר הפעילות שלך ברשת ובמכשיר, כולל הודעות אימייל, אפליקציות ואתרים."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"אתה מחובר לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת, כולל הודעות אימייל, אפליקציות ואתרים."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"אתה מחובר לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת הפרטית, כולל הודעות אימייל, אפליקציות ואתרים."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"אתה מחובר לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת הפרטית, כולל הודעות אימייל, אפליקציות ואתרים."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"פרופיל העבודה שלך מנוהל על-ידי <xliff:g id="ORGANIZATION">%1$s</xliff:g>. הוא מחובר ל-<xliff:g id="APPLICATION">%2$s</xliff:g>, אפליקציה שיכולה לעקוב אחרי הפעילות שלך ברשת, כולל פעילות באימייל, באפליקציות ובאתרים.\n\nלמידע נוסף, צור קשר עם מנהל המערכת."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"פרופיל העבודה שלך מנוהל על ידי <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_disabled" msgid="7412534203633528135">"המכשיר יישאר נעול עד שתבטל את נעילתו באופן ידני"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"קבל התראות מהר יותר"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 4ac5e07..97d5834 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -342,16 +342,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"閉じる"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"開く"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"充電が完了しました"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index c0b6b79..9e65155 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> გაფრთხილება"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"სამსახურის რეჟიმი"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"ღამის განათება"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC გათიშულია"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ჩართულია"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"ბოლოს გამოყენებული ერთეულები არ არის"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"ყველაფერი გასუფთავდა"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"აპლიკაციის შესახებ"</string>
@@ -340,16 +337,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"დახურვა"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"გახსნა"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"დატენილია"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"VPN-ის გათიშვა"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"თქვენ დაუკავშირდით <xliff:g id="VPN_APP">%1$s</xliff:g>-ს, რომელსაც თქვენი ქსელის აქტივობის, მათ შორის, ელფოსტის, აპებისა და ვებსაიტების, მონიტორინგი შეუძლია."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"VPN-ის პარამეტრების გახსნა"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"თქვენმა ადმინისტრატორმა ქსელის ჟურნალირება ჩართო, რომელიც თქვენი მოწყობილობის ტრაფიკის მონიტორინგს ახორციელებს.\n\nდამატებითი ინფორმაციისთვის დაუკავშირდით თქვენს ადმინისტრატორს."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"თქვენ მიეცით ნებართვა აპს, დააყენოს VPN კავშირი.\n\nამ აპს შეუძლია თქვენი მოწყობილობის და ქსელის აქტივობის, მათ შორის, ელფოსტის, აპებისა და ვებსაიტების მონიტორინგი."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"თქვენ დაუკავშირდით <xliff:g id="APPLICATION">%1$s</xliff:g>-ს, რომელსაც შეუძლია თქვენი ქსელის აქტივობის, მათ შორის, ელფოსტის, აპებისა და ვებსაიტების მონიტორინგი."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"თქვენ დაუკავშირდით <xliff:g id="APPLICATION">%1$s</xliff:g>-ს, რომელსაც შეუძლია თქვენი პირადი ქსელის აქტივობის, მათ შორის, ელფოსტის, აპებისა და ვებსაიტების მონიტორინგი."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"თქვენ დაუკავშირდით <xliff:g id="APPLICATION">%1$s</xliff:g>-ს, რომელსაც თქვენი პირადი ქსელის აქტივობის მონიტორინგი შეუძლია, მათ შორის, ელფოსტის, აპებისა და ვებსაიტების."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"თქვენს სამსახურის პროფილს მართავს <xliff:g id="ORGANIZATION">%1$s</xliff:g>. ის დაკავშირებულია <xliff:g id="APPLICATION">%2$s</xliff:g>-თან, რომელსაც თქვენი ქსელის აქტივობის (მათ შორის, ელფოსტის, აპებისა და ვებსაიტების) მონიტორინგი შეუძლია.\n\nდამატებითი ინფორმაციისთვის დაუკავშირდით თქვენს ადმინისტრატორს."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"თქვენი სამუშაო პროფილი <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_disabled" msgid="7412534203633528135">"მოწყობილობის დარჩება ჩაკეტილი, სანამ ხელით არ გახსნით"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"შეტყობინებების უფრო სწრაფად მიღება"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 69cd8bf..be32860 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> туралы ескерту"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Жұмыс режимі"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Түнгі жарық"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC өшірулі"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC қосулы"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Жақындағы элементтер жоқ"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Сіз барлығын өшірдіңіз"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Қолданба туралы ақпарат"</string>
@@ -340,16 +337,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Қабылдамау"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Ашу"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Зарядталды"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"VPN желісін ажырату"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Желідегі әрекеттерді, соның ішінде электрондық хабарларды, қолданбаларды және вебсайттарды бақылайтын <xliff:g id="VPN_APP">%1$s</xliff:g> қолданбасына қосылдыңыз."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"VPN параметрлерін ашу"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Әкімші құрылғыдағы трафикті қадағалау үшін желі журналын жүргізуді қосып қойған.\n\nТолығырақ ақпарат алу үшін әкімшімен хабарласыңыз."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Қолданбаға VPN байланысын орнату рұқсатын бердіңіз.\n\nБұл қолданба құрылғыңызды және желідегі белсенділігіңізді, соның ішінде электрондық пошталарды, қолданбаларды және веб-сайттарды бақылай алады."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"Сіз желідегі белсенділігіңізді, соның ішінде электрондық пошталарды, қолданбаларды және веб-сайттарды бақылай алатын <xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына қосылғансыз."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Сіз жеке желідегі белсенділігіңізді, соның ішінде электрондық пошталарды, қолданбаларды және веб-сайттарды бақылай алатын <xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына қосылғансыз."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Жеке желідегі әрекеттеріңізді, соның ішінде электрондық пошта хабарларын, қолданбаларды және вебсайттарды бақылай алатын <xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына қосылғансыз."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Жұмыс профиліңізді <xliff:g id="ORGANIZATION">%1$s</xliff:g> басқарады. Ол жұмыс барысындағы желідегі белсенділігіңізді, соның ішінде электрондық хабарларды, қолданбаларды және вебсайттарды бақылай алатын <xliff:g id="APPLICATION">%2$s</xliff:g> қолданбасына қосылған.\n\nҚосымша ақпарат алу үшін әкімшіге хабарласыңыз."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Жұмыс профиліңізді <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_disabled" msgid="7412534203633528135">"Қолмен бекітпесін ашқанша құрылғы бекітілген күйде қалады"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Хабарландыруларды тезірек алу"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 3b04eca..3d87668 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -340,16 +340,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"បដិសេធ"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"បើក"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"បាន​បញ្ចូល​ថ្ម​​"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index e26ac87..f13b8fde 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ಎಚ್ಚರಿಕೆ"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"ಕೆಲಸದ ಮೋಡ್"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"ನೈಟ್ ಲೈಟ್"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ಸಕ್ರಿಯಗೊಂಡಿದೆ"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"ಯಾವುದೇ ಇತ್ತೀಚಿನ ಐಟಂಗಳಿಲ್ಲ"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"ನೀವು ಎಲ್ಲವನ್ನೂ ತೆರವುಗೊಳಿಸಿರುವಿರಿ"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ"</string>
@@ -340,16 +337,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"ವಜಾಗೊಳಿಸಿ"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"ತೆರೆಯಿರಿ"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ಚಾರ್ಜ್ ಆಗಿದೆ"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"VPN ಸಂಪರ್ಕಕಡಿತಗೊಳಿಸಿ"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"ನೀವು ಇಮೇಲ್‌ಗಳು, ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ವೆಬ್‌ಸೈಟ್‌ಗಳನ್ನು ಒಳಗೊಂಡಂತೆ ನಿಮ್ಮ ನೆಟ್‌ವರ್ಕ್ ಚಟುವಟಿಕೆಯ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದಾದ, <xliff:g id="VPN_APP">%1$s</xliff:g> ಗೆ ನೀವು ಸಂಪರ್ಕಗೊಂಡಿರುವಿರಿ."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"VPN ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ತೆರೆಯಿರಿ"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ನೆಟ್‌ವರ್ಕ್ ಲಾಗಿಂಗ್ ಆನ್ ಮಾಡಿದ್ದಾರೆ. ಇದು ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿನ ಟ್ರಾಫಿಕ್ ಮೇಲೆ ನಿಗಾ ಇರಿಸುತ್ತದೆ.\n\nಹೆಚ್ಚಿನ ಮಾಹಿತಿಗೆ ನಿಮ್ಮ ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"ನೀವು VPN ಸಂಪರ್ಕ ಹೊಂದಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿ ನೀಡಿರುವಿರಿ.\n\nಈ ಅಪ್ಲಿಕೇಶನ್ ಇಮೇಲ್‌ಗಳು, ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ವೆಬ್‌ಸೈಟ್‌ಗಳನ್ನು ಒಳಗೊಂಡಂತೆ ನಿಮ್ಮ ನೆಟ್‌ವರ್ಕ್ ಚಟುವಟಿಕೆಯ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"ನೀವು ಇಮೇಲ್‌ಗಳು, ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ವೆಬ್‌ಸೈಟ್‌ಗಳನ್ನು ಒಳಗೊಂಡಂತೆ ನಿಮ್ಮ ನೆಟ್‌ವರ್ಕ್ ಚಟುವಟಿಕೆಯ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದಾದ <xliff:g id="APPLICATION">%1$s</xliff:g> ಗೆ ಸಂಪರ್ಕಗೊಂಡಿರುವಿರಿ."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"ನೀವು ಇಮೇಲ್‌ಗಳು, ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ವೆಬ್‌ಸೈಟ್‌ಗಳು ಸೇರಿದಂತೆ ನಿಮ್ಮ ವೈಯಕ್ತಿಕ ನೆಟ್‌ವರ್ಕ್ ಚಟುವಟಿಕೆಯ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದಾದ <xliff:g id="APPLICATION">%1$s</xliff:g> ಗೆ ಸಂಪರ್ಕಗೊಂಡಿರುವಿರಿ."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"ನೀವು ಇಮೇಲ್‌ಗಳು, ಅಪ್ಲಿಕೇಶನ್‌ಗಳು, ಮತ್ತು ವೆಬ್‌ಸೈಟ್‌ಗಳನ್ನು ಒಳಗೊಂಡಂತೆ ನಿಮ್ಮ ವೈಯಕ್ತಿಕ ನೆಟ್‌ವರ್ಕ್ ಚಟುವಟಿಕೆಯ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದಾದ <xliff:g id="APPLICATION">%1$s</xliff:g> ಗೆ ಸಂಪರ್ಕಗೊಂಡಿರುವಿರಿ."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್ ಅನ್ನು <xliff:g id="ORGANIZATION">%1$s</xliff:g> ನಿರ್ವಹಿಸುತ್ತಿದೆ. ಇಮೇಲ್‌ಗಳು, ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ವೆಬ್‌ಸೈಟ್‌ಗಳೂ ಸೇರಿದಂತೆ ನಿಮ್ಮ ಕೆಲಸದ ನೆಟ್‌ವರ್ಕ್ ಚಟುವಟಿಕೆಯ ಮೇಲೆ ನಿಗಾ ಇರಿಸಬಲ್ಲ <xliff:g id="APPLICATION">%2$s</xliff:g> ಗೆ ಇದು ಸಂಪರ್ಕ ಹೊಂದಿದೆ.\n\nಹೆಚ್ಚಿನ ಮಾಹಿತಿಗಾಗಿ, ನಿಮ್ಮ ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್‌ ಅನ್ನು <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_disabled" msgid="7412534203633528135">"ನೀವಾಗಿಯೇ ಅನ್‌ಲಾಕ್‌ ಮಾಡುವವರೆಗೆ ಸಾಧನವು ಲಾಕ್‌ ಆಗಿಯೇ ಇರುತ್ತದೆ"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"ವೇಗವಾಗಿ ಅಧಿಸೂಚನೆಗಳನ್ನು ಪಡೆದುಕೊಳ್ಳಿ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 62b5d47..fc60f7a 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -342,16 +342,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"닫기"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"열기"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"충전됨"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 2dc5c1d..90ae2c6 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> эскертүү"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Иштөө режими"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Түнкү жарык"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC өчүрүлгөн"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC иштетилген"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Акыркы колдонмолор жок"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Баарын тазаладыңыз"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Колдонмо жөнүндө маалымат"</string>
@@ -340,16 +337,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Этибарга албоо"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Ачуу"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Кубатталды"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"VPN\'ди ажыратуу"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Электрондук почта, колдонмолор жана вебсайттар сыяктуу тармактагы аракеттериңизди тескей турган <xliff:g id="VPN_APP">%1$s</xliff:g> колдонмосуна туташып турасыз."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"VPN жөндөөлөрүн ачуу"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Администраторуңуз тармактын таржымалын алууну иштетти, андыктан түзмөгүңүздөгү трафик көзөмөлгө алынды.\n\nКеңири маалымат алуу үчүн администраторуңузга кайрылыңыз."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Колдонмого VPN туташуусун орнотууга уруксат бердиңиз.\n\nБул колдонмо түзмөгүңүздү жана электрондук почталар, колдонмолор жана вебсайттар сыяктуу тармактагы аракеттериңизди көзөмөлдөй алат."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"Электрондук почта, колдонмолор жана вебсайттар сыяктуу тармактык аракеттерди көзөмөлдөй турган <xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосуна туташып турасыз."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Электрондук почта, колдонмолор жана вебсайттар сыяктуу тармактагы жеке аракеттериңизди көзөмөлдөй турган <xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосуна туташып турасыз."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Электрондук почта, колдонмолор жана вебсайттар сыяктуу тармактагы жеке аракеттериңизди тескей турган <xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосуна туташып турасыз."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Жумуш профилиңизди <xliff:g id="ORGANIZATION">%1$s</xliff:g> башкарат. Ал электрондук почта, колдонмолор жана вебсайттар сыяктуу жумуш тармагыңыздагы аракеттерди көзөмөлдөй турган <xliff:g id="APPLICATION">%2$s</xliff:g> менен туташкан.\n\nКөбүрөөк маалымат алуу үчүн администраторуңузга кайрылыңыз."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Жумуш профилиңизди <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_disabled" msgid="7412534203633528135">"Түзмөктүн кулпусу кол менен ачылмайынча кулпуланган бойдон алат"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Эскертмелерди тезирээк алуу"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 7fb5c1e..c639fa3 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"ຄຳ​ເຕືອນ <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"ໂໝດການເຮັດວຽກ"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"ແສງກາງຄືນ"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC is disabled"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC is enabled"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"ບໍ່ມີລາຍການຫຼ້າສຸດ"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"ທ່ານລຶບລ້າງທຸກຢ່າງແລ້ວ"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"​ຂໍ້​ມູນ​ແອັບ​ພ​ລິ​ເຄ​ຊັນ"</string>
@@ -340,16 +337,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"ປິດໄວ້"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"ເປີດ"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Split screen to the top"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Split screen to the left"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Split screen to the right"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ສາກເຕັມແລ້ວ."</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"ຕັດ​ການ​ເຊື່ອມ​ຕໍ່ VPN"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"ທ່ານເຊື່ອມຕໍ່ກັບ <xliff:g id="VPN_APP">%1$s</xliff:g> ແລ້ວ, ເຊິ່ງສາມາດຕິດຕາມການເຄື່ອນໄຫວເຄືອຂ່າຍ, ຮວມທັງອີເມວ, ແອັບ ແລະ ເວັບໄຊຕ່າງໆໄດ້."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"ເປີດການຕັ້ງຄ່າ VPN"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Your admin has turned on network logging, which monitors traffic on your device.\n\nFor more information, contact your admin."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"ທ່ານໄດ້ອະນຸຍາດໃຫ້ແອັບຕັ້ງການເຊື່ອມຕໍ່ VPN.\n\nແອັບນີ້ສາມາດຕິດຕາມການເຄື່ອນໄຫວຂອງອຸປະກອນ ແລະເຄືອຂ່າຍຂອງທ່ານ ເຊິ່ງລວມທັງອີເມວ, ແອັບ ແລະເວັບໄຊທ໌."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Your work profile is managed by <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nYour admin is capable of monitoring your network activity including emails, apps, and websites.\n\nFor more information, contact your admin.\n\nYou\'re also connected to a VPN, which can monitor your network activity."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"ທ່ານເຊື່ອມຕໍ່ກັບ <xliff:g id="APPLICATION">%1$s</xliff:g>, ເຊິ່ງສາມາດຕິດຕາມການເຄື່ອນໄຫວເຄືອຂ່າຍຂອງທ່ານ ລວມທັງອີເມວ, ​ແອັບ ແລະເວັບໄຊທ໌."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"ທ່ານເຊື່ອມຕໍ່ກັບ <xliff:g id="APPLICATION">%1$s</xliff:g>, ເຊິ່ງສາມາດຕິດຕາມການເຄື່ອນໄຫວເຄືອຂ່າຍສ່ວນຕົວຂອງທ່ານ ລວມທັງອີເມວ, ​ແອັບ ແລະເວັບໄຊທ໌."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"ທ່ານເຊື່ອມຕໍ່ກັບ <xliff:g id="APPLICATION">%1$s</xliff:g> ແລ້ວ, ເຊິ່ງສາມາດຕິດຕາມການເຄື່ອນໄຫວເຄືອຂ່າຍສ່ວນຕົວຂອງທ່ານ ຮວມທັງອີເມວ, ​ແອັບ ແລະເວັບໄຊໄດ້."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Your work profile is managed by <xliff:g id="ORGANIZATION">%1$s</xliff:g>. It is connected to <xliff:g id="APPLICATION">%2$s</xliff:g>, which can monitor your work network activity, including emails, apps, and websites.\n\nFor more information, contact your admin."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກຂອງທ່ານຖືກຈັດການໂດຍ <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_disabled" msgid="7412534203633528135">"Device will stay locked until you manually unlock"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"ຮັບເອົາການ​ແຈ້ງເຕືອນ​ໄວຂຶ້ນ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 6036842..a40bcb6 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -325,12 +325,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> įspėjimas"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Darbo režimas"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nakties šviesa"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"ALR"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"ALR išjungtas"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"ALR įjungtas"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nėra jokių naujausių elementų"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Viską išvalėte"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Programos informacija"</string>
@@ -344,16 +341,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horizontalus skaidymas"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikalus skaidymas"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Tinkintas skaidymas"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Atsisakyti"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Atidaryti"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Skaidyti ekraną į viršų"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Skaidyti ekraną į kairę"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Skaidyti ekraną į dešinę"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Įkrautas"</string>
@@ -434,24 +426,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Atjungti VPN"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Įrenginį tvarko „<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>“ naudoja „<xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g>“ įrenginiui tvarkyti."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"Administrat. gali stebėti ir tvark. nustat., įmonės prieigos par., progr., su įreng. susietus duomenis ir įreng. vietovės inform."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Sužinoti daugiau"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Esate prisijungę prie programos „<xliff:g id="VPN_APP">%1$s</xliff:g>“, kuri gali stebėti tinklo veiklą, įskaitant el. laiškus, programas ir svetaines."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Atidaryti VPN nustatymus"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administratorius įjungė tinklo duomenų įrašymą į žurnalą. Įjungus šią funkciją stebimas srautas jūsų įrenginyje.\n\nJei reikia daugiau informacijos, susisiekite su administratoriumi."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Suteikėte programai leidimą nustatyti VPN ryšį.\n\nŠi programa gali stebėti įrenginio ir tinklo veiklą, įskaitant el. laiškus, programas ir svetaines."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Jūsų darbo profilį tvarko „<xliff:g id="ORGANIZATION">%1$s</xliff:g>“.\n\nJūsų administratorius gali stebėti jūsų tinklo veiklą, įskaitant el. laiškus, programas ir svetaines.\n\nJei reikia daugiau informacijos, susisiekite su administratoriumi.\n\nTaip pat esate prisijungę prie VPN, kuris gali stebėti jūsų tinklo veiklą."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Esate prisijungę prie programos „<xliff:g id="APPLICATION">%1$s</xliff:g>“, kuri gali stebėti tinklo veiklą, įskaitant el. laiškus, programas ir svetaines."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Esate prisijungę prie programos „<xliff:g id="APPLICATION">%1$s</xliff:g>“, kuri gali stebėti asmeninio profilio tinklo veiklą, įskaitant el. laiškus, programas ir svetaines."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Esate prisijungę prie programos „<xliff:g id="APPLICATION">%1$s</xliff:g>“, kuri gali stebėti asmeninio tinklo veiklą, įskaitant el. laiškus, programas ir svetaines."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Jūsų darbo profilį tvarko „<xliff:g id="ORGANIZATION">%1$s</xliff:g>“. Jis susietas su programa „<xliff:g id="APPLICATION">%2$s</xliff:g>“, kuri negali stebėti jūsų tinklo veiklos, įskaitant el. laiškus, programas ir svetaines.\n\nJei reikia daugiau informacijos, susisiekite su administratoriumi."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Darbo profilį tvarko „<xliff:g id="ORGANIZATION">%1$s</xliff:g>“. Jis susietas su programa „<xliff:g id="APPLICATION_WORK">%2$s</xliff:g>“, kuri gali stebėti darbo profilio tinklo veiklą, įskaitant el. laiškus, programas ir svetaines.\n\nTaip pat esate prisijungę prie programos „<xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>“, kuri gali stebėti asmeninio profilio tinklo veiklą."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Įrenginys liks užrakintas, kol neatrakinsite jo neautomatiniu būdu"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Greičiau gaukite pranešimus"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 9911109..8ce3890 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -342,16 +342,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horizontāls dalījums"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikāls dalījums"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Pielāgots dalījums"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Noraidīt"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Atvērt"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Sadalīt ekrānu augšdaļā"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Sadalīt ekrānu kreisajā pusē"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Sadalīt ekrānu labajā pusē"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Akumulators uzlādēts"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 500cb4f..fa9489d 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Предупредување за <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Режим на работа"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Ноќно светло"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC е оневозможено"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC е овозможено"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Нема неодамнешни ставки"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Исчистивте сѐ"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Информации за апликацијата"</string>
@@ -340,16 +337,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Отфрлете"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Отворете"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Наполнета"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Исклучи ВПН"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Поврзани сте на <xliff:g id="VPN_APP">%1$s</xliff:g>, којашто може да ја следи вашата активност на мрежата, вклучувајќи ги е-пораките, апликациите и веб-сајтовите."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Отворете „Поставки за VPN“"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Вашиот администратор вклучил евиденција на мрежата, што подразбира следење на сообраќајот на вашиот уред.\n\nЗа повеќе информации, контактирајте со администраторот."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Дозволивте апликацијата да постави поврзување преку ВПН.\n\nАпликацијата може да го следи уредот и активноста на мрежата, вклучувајќи ги е-пораките, апликациите и веб-локациите."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> управува со вашиот работен профил.\n\nАдминистратор е во можност да ја следи вашата активност на мрежата, вклучувајќи ги е-пораките, апликациите и веб-локациите.\n\nЗа повеќе информации, контактирајте со администраторот.\n\nYИсто така, поврзани сте на VPN којашто може да ја следи вашата активност на мрежата."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"ВПН"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Поврзани сте на <xliff:g id="APPLICATION">%1$s</xliff:g>, којашто може да ја следи вашата активност на мрежата, вклучувајќи ги е-пораките, апликациите и веб-локациите."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Поврзани сте на <xliff:g id="APPLICATION">%1$s</xliff:g>, којашто може да ја следи вашата лична активност на мрежата, вклучувајќи ги е-пораките, апликациите и веб-локациите."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Поврзани сте на <xliff:g id="APPLICATION">%1$s</xliff:g>, којашто може да ја следи вашата лична активност на мрежата, вклучувајќи ги е-пораките, апликациите и веб-локациите."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> управува со вашиот работен профил. Истиот е поврзан на <xliff:g id="APPLICATION">%2$s</xliff:g>, којашто може да ја следи вашата работна активност на мрежата, вклучувајќи ги е-пораките, апликациите и веб-локациите.\n\nЗа повеќе информации, контактирајте со администраторот."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"<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_disabled" msgid="7412534203633528135">"Уредот ќе остане заклучен додека рачно не го отклучите"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Добивајте известувања побрзо"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 1787d21..313bf9c 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> മുന്നറിയിപ്പ്"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"പ്രവർത്തന മോഡ്"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"നൈറ്റ് ലൈറ്റ്"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC പ്രവർത്തനരഹിതമാക്കി"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC പ്രവർത്തനക്ഷമമാക്കി"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"സമീപകാല ഇനങ്ങൾ ഒന്നുമില്ല"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"നിങ്ങൾ എല്ലാം മായ്ച്ചിരിക്കുന്നു"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"ആപ്പ് വിവരം"</string>
@@ -340,16 +337,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"ഒഴിവാക്കുക"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"തുറക്കുക"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ചാർജായി"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"VPN വിച്‌ഛേദിക്കുക"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"ക്രമീകരണങ്ങൾ, കോർപ്പറേറ്റ് ആക്‌സസ്സ്, ആപ്‌സ്, ഉപകരണത്തിന്റെ ഡാറ്റ, ലൊക്കേഷൻ എന്നിവ നിരീക്ഷിക്കാനും നിയന്ത്രിക്കാനും അഡ്‌മിന് കഴിയും."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" 5"</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"കൂടുതലറിയുക"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"നിങ്ങൾ <xliff:g id="VPN_APP">%1$s</xliff:g> ആപ്പിലേക്ക് കണക്റ്റുചെയ്‌തിരിക്കുന്നു, ഇമെയിലുകൾ, ആപ്‌സ്, വെബ്‌സൈറ്റുകൾ എന്നിവ ഉൾപ്പെടെ നിങ്ങളുടെ നെറ്റ്‌വർക്ക് ആക്റ്റിവിറ്റി നിരീക്ഷിക്കാൻ ഈ ആപ്പിന് കഴിയും."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" 5"</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"VPN ക്രമീകരണം തുറക്കുക"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"നിങ്ങളുടെ ഉപകരണത്തിലെ ട്രാഫിക്ക് നിരീക്ഷിക്കുന്ന നെറ്റ്‌വർക്ക് ലോഗിംഗ് അഡ്‌മിൻ ഓണാക്കിയിട്ടുണ്ട്.\n\nകൂടുതൽ ‌വിവരങ്ങൾക്ക് അഡ്‌മിനുമായി‌ ബന്ധപ്പെടുക."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"VPN കണക്ഷൻ സജ്ജീകരിക്കാൻ നിങ്ങൾ ഒരു ആപ്പിന് അനുമതി നൽകി.\n\nഈ ആപ്പിന് നിങ്ങളുടെ ഇമെയിലുകളും ആപ്സും വെബ്‌സൈറ്റുകളും ഉൾപ്പെടെ, ഉപകരണവും നെറ്റ്‌വർക്ക് പ്രവർത്തനവും നിരീക്ഷിക്കാൻ കഴിയും."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"നിങ്ങൾ <xliff:g id="APPLICATION">%1$s</xliff:g> എന്നതിലേക്ക് കണക്റ്റുചെയ്‌തിരിക്കുന്നു, അതിന് ഇമെയിലുകൾ, ആപ്സ്, വെബ്‌സൈറ്റുകൾ എന്നിവ ഉൾപ്പെടെ നിങ്ങളുടെ നെറ്റ്‌വർക്ക് പ്രവർത്തനം നിരീക്ഷിക്കാനാകും."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"നിങ്ങൾ <xliff:g id="APPLICATION">%1$s</xliff:g> എന്നതിലേക്ക് കണക്റ്റുചെയ്‌തിരിക്കുന്നു, അതിന് ഇമെയിലുകൾ, ആപ്സ്, വെബ്‌സൈറ്റുകൾ എന്നിവ ഉൾപ്പെടെ നിങ്ങളുടെ സ്വകാര്യ നെറ്റ്‌വർക്ക് പ്രവർത്തനം നിരീക്ഷിക്കാനാകും."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"നിങ്ങൾ <xliff:g id="APPLICATION">%1$s</xliff:g> ആപ്പിലേക്ക് കണക്റ്റുചെയ്‌തിരിക്കുന്നു, ഇമെയിലുകൾ, ആപ്‌സ്, വെബ്‌സൈറ്റുകൾ എന്നിവ ഉൾപ്പെടെ നെറ്റ്‌വർക്ക് ആക്റ്റിവിറ്റി നിരീക്ഷിക്കാൻ ഈ ആപ്പിന് കഴിയും."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈൽ നിയന്ത്രിക്കുന്നത് <xliff:g id="ORGANIZATION">%1$s</xliff:g> ആണ്. ഇമെയിൽ, ആപ്പുകൾ, ‌വെബ്‌സൈറ്റുകൾ എന്നിവയടങ്ങുന്ന നിങ്ങളുടെ നെറ്റ്‌വർക്ക് ആക്റ്റിവിറ്റി നിരീക്ഷിക്കാൻ സാധിക്കുന്ന <xliff:g id="APPLICATION">%2$s</xliff:g> എന്നതിലേക്ക് ഇത് ‌കണക്റ്റ്‌ ചെയ്യപ്പെട്ടിരിക്കുന്നു.\n\nകൂടുതൽ ‌വിവരങ്ങൾക്ക് അഡ്‌മിനുമായി‌ ബന്ധപ്പെടുക."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈൽ നിയന്ത്രിക്കുന്നത് <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_disabled" msgid="7412534203633528135">"നിങ്ങൾ സ്വമേധയാ അൺലോക്കുചെയ്യുന്നതുവരെ ഉപകരണം ലോക്കുചെയ്‌തതായി തുടരും"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"അറിയിപ്പുകൾ വേഗത്തിൽ സ്വീകരിക്കുക"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index b8b9222..873f5a5 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -319,12 +319,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> анхааруулга"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Ажлын горим"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Шөнийн гэрэл"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC-г цуцалсан"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC-г идэвхжүүлсэн"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Сүүлийн үеийн зүйл байхгүй"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Та бүгдийг нь устгасан"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Аппликешны мэдээлэл"</string>
@@ -338,16 +335,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Хаах"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Нээх"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Цэнэглэгдсэн"</string>
@@ -428,24 +420,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"VPN таслах"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Таны имэйл, апп, вэб хуудас зэрэг сүлжээний үйл ажиллагааг хянах боломжтой <xliff:g id="VPN_APP">%1$s</xliff:g>-д холбогдсон байна."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"VPN тохиргоог нээх"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Таны админ төхөөрөмжийн ачааллыг хянадаг сүлжээний логийг асаасан байна.\n\nДэлгэрэнгүй мэдээлэл авах бол админтайгаа холбогдоно уу."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Та апп-д VPN холболт хийхийг зөвшөөрсөн байна.\n\nЭнэхүү апп нь таны имэйл, апп, вэбсайт зэрэг төхөөрөмж болон сүлжээний үйл ажиллагааг хянах боломжтой."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"Та <xliff:g id="APPLICATION">%1$s</xliff:g>-д холбогдсон бөгөөд энэ нь таны имэйл, апп, вэбсайт зэрэг сүлжээний үйл ажиллагааг хянах боломжтой."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Та <xliff:g id="APPLICATION">%1$s</xliff:g>-д холбогдсон бөгөөд энэ нь таны имэйл, апп, вэбсайт зэрэг сүлжээний хувийн үйл ажиллагааг хянах боломжтой."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Та имэйл, апп, вэб хуудас зэрэг хувийн сүлжээнийхээ үйл ажиллагааг хянах боломжтой <xliff:g id="APPLICATION">%1$s</xliff:g>-д холбогдсон байна."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> таны ажлын профайлыг удирддаг. Энэ нь таны имэйл, апп, вэб хуудас зэрэг ажлын сүлжээний үйл ажиллагааг хянах боломжтой <xliff:g id="APPLICATION">%2$s</xliff:g>-тэй холбогдсон.\n\nДэлгэрэнгүй мэдээлэл авах бол админтайгаа холбогдоно уу."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Таны ажлын профайлыг <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_disabled" msgid="7412534203633528135">"Таныг гараар онгойлгох хүртэл төхөөрөмж түгжээтэй байх болно"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Мэдэгдлийг хурдан авах"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 4c8d59c..1beae47 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> चेतावणी"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"कार्य मोड"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"रात्रीचा प्रकाश"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC अक्षम केले आहे"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC सक्षम केले आहे"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"अलीकडील कोणतेही आयटम नाहीत"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"आपण सर्वकाही साफ केले"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"अनुप्रयोग माहिती"</string>
@@ -430,24 +427,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"VPN डिस्कनेक्ट करा"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"आपण <xliff:g id="VPN_APP">%1$s</xliff:g> शी कनेक्‍ट केले आहे, जो ईमेल, अ‍ॅप्स आणि वेबसाइटसह आपल्‍या नेटवर्क क्रियाकलापाचे परीक्षण करू शकतो."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"VPN सेटिंग्ज उघडा"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"आपल्या प्रशासकाने नेटवर्क लॉगिंग चालू केले आहे, जे आपल्या डिव्हाइसवरील रहदारीचे निरीक्षण करते.\n\nअधिक माहितीसाठी आपल्या प्रशासकाशी संपर्क साधा."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"आपण VPN कनेक्शन सेट करण्यासाठी अ‍ॅपला परवानगी दिली.\n\nहा अ‍ॅप ईमेल, अ‍ॅप्स आणि वेबसाइटसह, आपल्या डिव्हाइस आणि नेटवर्क क्रियाकलापाचे परीक्षण करू शकतो."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"आपण <xliff:g id="APPLICATION">%1$s</xliff:g> शी कनेक्‍ट केले आहे, जो ईमेल, अ‍ॅप्स आणि वेबसाइटसह आपल्‍या नेटवर्क क्रियाकलापाचे परीक्षण करू शकतो."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"आपण <xliff:g id="APPLICATION">%1$s</xliff:g> शी कनेक्‍ट केले आहे, जो ईमेल, अ‍ॅप्स आणि वेबसाइटसह आपल्‍या वैयक्तिक नेटवर्क क्रियाकलापाचे परीक्षण करू शकतो."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"आपण <xliff:g id="APPLICATION">%1$s</xliff:g> शी कनेक्‍ट केले आहे, जो ईमेल, अ‍ॅप्स आणि वेबसाइटसह आपल्‍या वैयक्तिक नेटवर्क क्रियाकलापाचे परीक्षण करू शकतो."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"आपले कार्य प्रोफाइल <xliff:g id="ORGANIZATION">%1$s</xliff:g> द्वारे व्यवस्थापित केले जाते. ते <xliff:g id="APPLICATION">%2$s</xliff:g> शी कनेक्ट केलेले आहे, जे ईमेल, अॅप्स आणि वेबसाइटच्या समावेशासह आपल्या कार्य नेटवर्क क्रियाकलापाचे निरीक्षण करते. \n\nअधिक माहितीसाठी आपल्या प्रशासकाशी संपर्क साधा."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"आपले कार्य प्रोफाईल <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_disabled" msgid="7412534203633528135">"आपण व्यक्तिचलितपणे अनलॉक करेपर्यंत डिव्हाइस लॉक केलेले राहील"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"सूचना अधिक जलद मिळवा"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 6e29cc9..21873fe1 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -340,16 +340,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Mendatar Terpisah"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Menegak Terpisah"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Tersuai Terpisah"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Ketepikan"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Buka"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Pisahkan skrin ke atas"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Pisahkan skrin ke kiri"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Pisahkan skrin ke kanan"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Sudah dicas"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index a439a01..b920279 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> သတိပေးချက်"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"အလုပ် မုဒ်"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"ညအလင်းရောင်"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC ကို ပိတ်ထားသည်"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ကို ဖွင့်ထားသည်"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"မကြာမီကဖွင့်ထားသည်များ မရှိပါ"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"သင်အားလုံးကို ရှင်းလင်းပြီးပါပြီ"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"အပလီကေးရှင်းအင်ဖို"</string>
@@ -340,16 +337,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"ပယ်ရန်"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"ဖွင့်ရန်"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"အားသွင်းပြီး"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"VPN ကို အဆက်ဖြတ်ရန်"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"အီးမေးလ်၊ အက်ပ်နှင့် ဝဘ်ဆိုက်များအပါအဝင် သင့်ကွန်ရက်လုပ်ဆောင်ချက်ကို စောင့်ကြည့်နိုင်သည့် <xliff:g id="VPN_APP">%1$s</xliff:g> သို့ သင်သည် ချိတ်ဆက်ထားပါသည်။"</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Open VPN ဆက်တင်များ"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"သင့်စီမံခန့်ခွဲသူသည် စက်ပစ္စည်းပေါ်ရှိ ဒေတာအသွားအလာကို စောင့်ကြည့်နိုင်သည့် ကွန်ရက်အတွက် မှတ်တမ်းတင်ခြင်းကို ဖွင့်ထားပါသည်။\n\nနောက်ထပ် အချက်အလက်များအတွက် သင့်စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ။"</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"VPN ချိတ်ဆက်မှုပြုလုပ်ရန် အက်ပ်ကို သင်ခွင့်ပြုလိုက်သည်။ \n\n ဤအက်ပ်သည် အီးမေးလ်များ၊ အက်ပ်များနှင့် ဝဘ်ဆိုက်များအပါအဝင် သင့်ကွန်ရက်လုပ်ဆောင်ချက်များကို စောင့်ကြည့်နိုင်သည်။"</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"သင်သည် <xliff:g id="APPLICATION">%1$s</xliff:g> သို့ ချိတ်ဆက်ထားသည်၊ ၎င်းသည် အီးမေးများ၊ အက်ပ်များနှင့် ဝဘ်ဆိုက်များအပါအဝင် သင့်ကွန်ရက်လုပ်ဆောင်ချက်များကို စောင့်ကြည့်နိုင်သည်။"</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"သင်သည် <xliff:g id="APPLICATION">%1$s</xliff:g> သို့ ချိတ်ဆက်ထားသည်။ ၎င်းသည် အီးမေးလ်များ၊ အက်ပ်များနှင့် ဝဘ်ဆိုက်များအပါအဝင် သင့်ကွန်ရက်လုပ်ဆောင်ချက်ကို စောင့်ကြည့်နိုင်သည်။"</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"သင်သည် အီးမေးလ်၊ အက်ပ်နှင့် ဝဘ်ဆိုက်များအပါအဝင် သင့်ကိုယ်ရေးကိုယ်တာ ကွန်ရက်အသုံးပြုမှုကို စောင့်ကြည့်နိုင်သည့် <xliff:g id="APPLICATION">%1$s</xliff:g> သို့ ချိတ်ဆက်ထားပါသည်။"</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"သင့်အလုပ်ပရိုဖိုင်ကို <xliff:g id="ORGANIZATION">%1$s</xliff:g> က စီမံခန့်ခွဲထားပါသည်။ ၎င်းသည် အီးမေးလ်၊ အက်ပ်နှင့် ဝဘ်ဆိုက်များအပါအဝင် သင့်ကွန်ရက်လုပ်ဆောင်ချက်များကို စောင့်ကြည့်နိုင်သည့် <xliff:g id="APPLICATION">%2$s</xliff:g> သို့ ချိတ်ဆက်ထားပါသည်။\n\nနောက်ထပ် အချက်အလက်များအတွက် သင့်စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ။"</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"သင့်အလုပ် ပရိုဖိုင်ကို <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_disabled" msgid="7412534203633528135">"သင်က လက်ဖြင့် သော့မဖွင့်မချင်း ကိရိယာမှာ သော့ပိတ်လျက် ရှိနေမည်"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"အကြောင်းကြားချက်များ မြန်မြန်ရရန်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index d95dd29..bb08967 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Advarsel for <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Arbeidsmodus"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nattlys"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC er slått av"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC er slått på"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Ingen nylige elementer"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Du har fjernet alt"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Appinformasjon"</string>
@@ -340,16 +337,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Del horisontalt"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Del vertikalt"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Del tilpasset"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Avvis"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Åpne"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Delt skjerm øverst"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Delt skjerm til venstre"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Delt skjerm til høyre"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Oppladet"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Koble fra VPN"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Enheten din administreres av <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> bruker <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> til å administrere enheten din."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"Administratoren din kan overvåke og administrere innstillinger, bedriftstilgang, apper, data som er tilknyttet denne enheten, og enhetens posisjonsinformasjon."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Finn ut mer"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Enheten er koblet til <xliff:g id="VPN_APP">%1$s</xliff:g>, som kan overvåke nettverksaktiviteten din, inkludert e-post, apper og nettsteder."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Åpne VPN-innstillingene"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administratoren din har slått på loggføring av nettverk, som overvåker trafikken på enheten din.\n\nKontakt administratoren for mer informasjon."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Du ga en app tillatelse til å konfigurere en VPN-tilkobling.\n\nDenne appen kan overvåke enheten og nettverksaktiviteten din, inkludert e-post, apper og nettsteder."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Jobbprofilen din administreres av <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministratoren din kan overvåke nettverksaktiviteten din, inkludert e-post, apper og nettsteder.\n\nKontakt administratoren for mer informasjon.\n\nDu er også tilkoblet en VPN som kan overvåke nettverksaktiviteten din."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Enheten er koblet til <xliff:g id="APPLICATION">%1$s</xliff:g>, som kan overvåke nettverksaktiviteten din, inkludert e-post, apper og nettsteder."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Enheten er koblet til <xliff:g id="APPLICATION">%1$s</xliff:g>, som kan overvåke den personlige nettverksaktiviteten din, inkludert e-post, apper og nettsteder."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Enheten er koblet til <xliff:g id="APPLICATION">%1$s</xliff:g>, som kan overvåke den personlige nettverksaktiviteten din, inkludert e-post, apper og nettsteder."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Jobbprofilen din administreres av <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Den er koblet til <xliff:g id="APPLICATION">%2$s</xliff:g>, som kan overvåke nettverksaktiviteten din, inkludert e-poster, apper og nettsteder.\n\nKontakt administratoren din for mer informasjon."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Work-profilen din administreres av <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Den er koblet til <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, som kan overvåke nettverksaktiviteten din på jobben, inkludert e-post, apper og nettsteder.\n\nDu er også koblet til <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, som kan overvåke den personlige nettverksaktiviteten din."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Enheten forblir låst til du låser den opp manuelt"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Motta varsler raskere"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 296d934..da856a6 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> चेतावनी दिँदै"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"कार्य मोड"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"रात्रिको प्रकाश"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC लाई असक्षम पारिएको छ"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC लाई सक्षम पारिएको छ"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"हालका कुनै पनि वस्तुहरू छैनन्"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"तपाईँले सबै कुरा खाली गर्नुभएको छ"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"अनुप्रयोग जानकारी"</string>
@@ -430,24 +427,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"विच्छेद VPN"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"तपाईं <xliff:g id="VPN_APP">%1$s</xliff:g> मा जोडिनुभएको छ जसले इमेल, अनुप्रयोग र वेबसाइटहरू लगायत तपाईंको नेटवर्क सम्बन्धी गतिविधिको अनुगमन गर्न सक्छ।"</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"VPN सम्बन्धी सेटिङहरू खोल्नुहोस्"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"तपाईँको प्रशासकले तपाईँको यन्त्रमा ट्राफिकको निगरानी गर्ने नेटवर्कको लगिङलाई सक्रिय पार्नुभएको छ।\n\nथप जानकारीका लागि आफ्नो प्रशासकलाई सम्पर्क गर्नुहोस्।"</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"तपाईँले VPN जडान गर्न अनुप्रयोगलाई अनुमति दिनुभयो।\n\nयो अनुप्रयोगले तपाईँका यन्त्र र  नेटवर्क गतिविधि लगायत इमेल, अनुप्रयोग र वेबसाइटहरू अनुगमन गर्न सक्छ।"</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"तपाईँको कार्य प्रोफाइल <xliff:g id="ORGANIZATION">%1$s</xliff:g> ले व्यवस्थापन गर्दछ।\n\nतपाईँको प्रशासकले तपाईँको इमेल, अनुप्रयोग र वेबसाइट सहित नेटवर्कमा तपाईँको गतिविधिको निगरानी गर्न सक्नुहुन्छ। \n\nथप जानकारीका लागि आफ्नो प्रशासकलाई सम्पर्क गर्नुहोस्।\n\n तपाईँ एउटा VPN मा जडित हुनुहुन्छ। यस VPN ले नेटवर्कमा तपाईँको गतिविधिको निगरानी गर्न सक्छ।"</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"तपाईँ <xliff:g id="APPLICATION">%1$s</xliff:g> सँग जडित हुनुहुन्छ जसले इ-मेल, अनुप्रयोगहरू र वेबसाइट लगायतका तपाईँका नेटवर्क गतिविधिको अनुगमन गर्न सक्छ।"</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"तपाईँ <xliff:g id="APPLICATION">%1$s</xliff:g> सँग जडित हुनुहुन्छ जसले इ-मेल, अनुप्रयोगहरू र वेबसाइट लगायतका तपाईँको निजी नेटवर्क गतिविधिका अनुगमन गर्न सक्छ।"</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"तपाईं <xliff:g id="APPLICATION">%1$s</xliff:g> मा जोडिनुभएको छ जसले इमेल, अनुप्रयोग र वेबसाइटहरू लगायतको तपाईंको  व्यक्तिगत नेटवर्क सम्बन्धी गतिविधिको अनुगमन गर्न सक्छ।"</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"तपाईँको कार्य प्रोफाइल <xliff:g id="ORGANIZATION">%1$s</xliff:g> ले व्यवस्थापन गर्दछ। तपाईँको कार्य प्रोफाइल <xliff:g id="APPLICATION">%2$s</xliff:g> मा जोडिएको छ। यो अनुप्रयोगले तपाईँको इमेल, अन्य अनुप्रयोग र वेबसाइटहरू सहित नेटवर्कमा तपाईँको गतिविधिको निगरानी गर्न सक्छ।\n\nथप जानकारीका लागि आफ्नो प्रशासकलाई सम्पर्क गर्नुहोस्।"</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"तपाईँको कार्य प्रोफाइल <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_disabled" msgid="7412534203633528135">"तपाईँले नखोले सम्म उपकरण बन्द रहनेछ"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"छिटो सूचनाहरू प्राप्त गर्नुहोस्"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index cfb030d..87c0860 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Waarschuwing voor <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Werkmodus"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nachtverlichting"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC is uitgeschakeld"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC is ingeschakeld"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Geen recente items"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Je hebt alles gewist"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"App-informatie"</string>
@@ -340,16 +337,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Horizontaal splitsen"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Verticaal splitsen"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Aangepast splitsen"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Sluiten"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Openen"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Scherm bovenaan gesplitst"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Scherm links gesplitst"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Scherm rechts gesplitst"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Opgeladen"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Verbinding met VPN verbreken"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Je apparaat wordt beheerd door <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> gebruikt <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> om je apparaat te beheren."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"Je beheerder kan instellingen, zakelijke toegang, apps, aan je apparaat gekoppelde gegevens en de locatiegegevens van je apparaat controleren en beheren."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Meer informatie"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Je bent verbonden met <xliff:g id="VPN_APP">%1$s</xliff:g>, waarmee je netwerkactiviteit (waaronder e-mails, apps en websites) kan worden gecontroleerd."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"VPN-instellingen openen"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Je beheerder heeft netwerkregistratie ingeschakeld, waarmee verkeer op je apparaat wordt bijgehouden.\n\nNeem contact op met je beheerder voor meer informatie."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Je hebt een app toestemming gegeven voor het instellen van een VPN-verbinding.\n\nMet deze app kan je apparaat- en netwerkactiviteit worden gecontroleerd, inclusief e-mails, apps en websites."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Je werkprofiel wordt beheerd door <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nJe beheerder kan je netwerkactiviteit controleren, inclusief e-mails, apps en websites.\n\nNeem contact op met je beheerder voor meer informatie.\n\nJe bent ook verbonden met een VPN, waarmee je netwerkactiviteit kan worden gecontroleerd."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"U bent verbonden met <xliff:g id="APPLICATION">%1$s</xliff:g>, waarmee je netwerkactiviteit kan worden gecontroleerd, inclusief e-mails, apps en websites."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"U bent verbonden met <xliff:g id="APPLICATION">%1$s</xliff:g>, waarmee je persoonlijke netwerkactiviteit kan worden gecontroleerd, inclusief e-mails, apps en websites."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Je bent verbonden met <xliff:g id="APPLICATION">%1$s</xliff:g>, waarmee je persoonlijke netwerkactiviteit kan worden gecontroleerd, inclusief e-mails, apps en websites."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Je werkprofiel wordt beheerd door <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Het is gekoppeld aan <xliff:g id="APPLICATION">%2$s</xliff:g>, waarmee je werkgerelateerde netwerkactiviteit kan worden gecontroleerd, inclusief e-mails, apps en websites.\n\nNeem contact op met je beheerder voor meer informatie."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Je werkprofiel wordt beheerd door <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Deze is verbonden met <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, waarmee je werkgerelateerde netwerkactiviteit kan worden gecontroleerd, inclusief e-mails, apps en websites.\n\nU bent ook verbonden met <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, waarmee je persoonlijke netwerkactiviteit kan worden gecontroleerd."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Het apparaat blijft vergrendeld totdat u het handmatig ontgrendelt"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Sneller meldingen ontvangen"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 0ec824d..f4e551d2 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> ਚਿਤਾਵਨੀ"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"ਕੰਮ ਮੋਡ"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"ਰਾਤਰੀ ਲਾਈਟ"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC ਨੂੰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ਨੂੰ ਯੋਗ ਬਣਾਇਆ ਗਿਆ"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"ਕੋਈ ਹਾਲੀਆ ਆਈਟਮਾਂ ਨਹੀਂ"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"ਤੁਸੀਂ ਸਭ ਕੁਝ ਸਾਫ਼ ਕਰ ਦਿੱਤਾ ਹੈ"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"ਐਪਲੀਕੇਸ਼ਨ ਜਾਣਕਾਰੀ"</string>
@@ -340,16 +337,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"ਖਾਰਜ ਕਰੋ"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"ਖੋਲ੍ਹੋ"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ਚਾਰਜ ਹੋਇਆ"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"VPN ਨੂੰ ਡਿਸਕਨੈਕਟ ਕਰੋ"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"ਤੁਸੀਂ <xliff:g id="VPN_APP">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੋ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ, ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।"</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"VPN ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹੋ"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਨੇ ਨੈੱਟਵਰਕ ਲੌਗਿੰਗ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਹੋਇਆ ਹੈ, ਜਿਸ ਨਾਲ ਤੁਹਾਡੀ ਡੀਵਾਈਸ \'ਤੇ ਟ੍ਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਹੁੰਦੀ ਹੈ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"ਤੁਸੀਂ ਇੱਕ ਐਪ ਨੂੰ ਇੱਕ VPN ਕਨੈਕਸ਼ਨ ਸੈਟ ਅਪ ਕਰਨ ਦੀ ਅਨੁਮਤੀ ਦਿੱਤੀ ਹੈ।\n\nਇਹ ਐਪ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਅਤੇ ਨੈੱਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰ ਸਕਦਾ ਹੈ, ਈਮੇਲਾਂ, ਐਪਸ ਅਤੇ ਸੁਰੱਖਿਅਤ ਵੈਬਸਾਈਟਾਂ ਸਮੇਤ।"</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"ਤੁਸੀਂ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੋ, ਜੋ ਈਮੇਲ, ਐਪਸ ਅਤੇ ਵੈਬਸਫ਼ਿਆਂ ਸਮੇਤ ਤੁਹਾਡੀ ਨੈੱਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰ ਸਕਦੀ ਹੈ।"</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"ਤੁਸੀਂ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੋ, ਜੋ ਈਮੇਲ, ਐਪਸ ਅਤੇ ਵੈਬਸਫ਼ਿਆਂ ਸਮੇਤ ਤੁਹਾਡੀ ਨੈੱਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰ ਸਕਦੀ ਹੈ।"</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"ਤੁਸੀਂ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੋ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ, ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਨਿੱਜੀ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।"</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"ਤੁਹਾਡੇ ਕਾਰਜ ਪ੍ਰੋਫ਼ਾਈਲ ਦਾ ਪ੍ਰਬੰਧਨ <xliff:g id="ORGANIZATION">%1$s</xliff:g> ਵੱਲੋਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਇਹ <xliff:g id="APPLICATION">%2$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੈ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ, ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਕਾਰਜ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"ਤੁਹਾਡੀ ਕਾਰਜ ਪ੍ਰੋਫ਼ਾਈਲ <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_disabled" msgid="7412534203633528135">"ਡੀਵਾਈਸ ਲੌਕ ਰਹੇਗੀ ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਮੈਨੂਅਲੀ ਅਨਲੌਕ ਨਹੀਂ ਕਰਦੇ"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"ਤੇਜ਼ੀ ਨਾਲ ਸੂਚਨਾਵਾਂ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 4926e30..457f644 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -344,16 +344,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Podziel poziomo"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Podziel pionowo"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Podziel niestandardowo"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Zamknij"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Otwórz"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Podziel ekran u góry"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Podziel ekran z lewej"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Podziel ekran z prawej"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Naładowana"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index c89cdc9..7edebe0 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -323,12 +323,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Aviso de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modo de trabalho"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Modo noturno"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"A NFC está desativada"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"A NFC está ativada"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nenhum item recente"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Você limpou tudo"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informações do app"</string>
@@ -342,16 +339,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisão horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisão vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisão personalizada"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Dispensar"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Abrir"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Dividir a tela para a parte superior"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Dividir a tela para a esquerda"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Dividir a tela para a direita"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
@@ -432,24 +424,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Desconectar VPN"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Seu dispositivo é gerenciado por <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> usa <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> para gerenciar seu dispositivo."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"O admin. pode monitorar e gerenciar config., acesso corporativo, apps, dados associados ao dispos. e info de local do dispositivo."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Saber mais"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Você está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorar sua atividade na rede, incluindo e-mails, apps e websites."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Abrir configurações de VPN"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Seu administrador ativou o registro de rede, que monitora o tráfego no seu dispositivo.\n\nPara ver mais informações, entre em contato com o administrador."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Você deu permissão para um app configurar uma conexão VPN.\n\nEsse app pode monitorar seu dispositivo e a atividade na rede, incluindo e-mails, apps e websites."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Seu perfil de trabalho é gerenciado por <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nSeu administrador pode monitorar sua atividade de rede, incluindo e-mails, apps e websites.\n\nPara ver mais informações, entre em contato com o administrador.\n\nVocê também está conectado a uma VPN, que pode monitorar sua atividade de rede."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Você está conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorar sua atividade na rede, incluindo e-mails, apps e websites."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Você está conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorar sua atividade pessoal na rede, incluindo e-mails, apps e websites."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Você está conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorar sua atividade pessoal na rede, incluindo e-mails, apps e websites."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Seu perfil de trabalho é gerenciado por <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Ele está conectado ao app <xliff:g id="APPLICATION">%2$s</xliff:g>, que pode monitorar sua atividade profissional de rede, incluindo e-mails, apps e websites.\n\nPara ver mais informações, entre em contato com o administrador."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Seu perfil de trabalho é gerenciado por <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Ele está conectado a <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, que pode monitorar sua atividade profissional na rede, incluindo e-mails, apps e websites.\n\nVocê também está conectado a <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, que pode monitorar sua atividade pessoal na rede."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"O dispositivo permanecerá bloqueado até que você o desbloqueie manualmente"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Receba notificações mais rápido"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 5f87c12..d7b40ff 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Aviso de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modo de trabalho"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Luz noturna"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"O NFC está desativado"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"O NFC está ativado"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nenhum item recente"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Limpou tudo"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informações da aplicação"</string>
@@ -340,16 +337,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisão horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisão vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisão personalizada"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Ignorar"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Abrir"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Ecrã dividido à parte superior"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Ecrã dividido à esquerda"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Ecrã dividido à direita"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Desligar VPN"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"O seu dispositivo é gerido pelo <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g>."</string>
     <string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"A <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> utiliza o <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> para gerir o seu dispositivo."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"O administ. pode monitorizar e gerir definições, acesso empresarial, aplic. e dados associados ao dispositivo, bem como inf. de localiz. do disp."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Saiba mais"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Websites."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Abrir as definições de VPN"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"O seu administrador ativou os registos de rede, que monitorizam o tráfego no seu dispositivo.\n\nPara obter mais informações, contacte o administrador."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Concedeu autorização a uma aplicação para configurar uma ligação VPN.\n\nEsta aplicação pode monitorizar a atividade do dispositivo e da rede, incluindo emails, aplicações e Websites."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"O seu perfil de trabalho é gerido por <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nO seu administrador tem a capacidade de monitorizar a sua atividade da rede, incluindo emails, aplicações e Websites.\n\nPara obter mais informações, contacte o administrador.\n\nAlém disso, está ligado a uma VPN, que pode monitorizar a sua atividade da rede."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Está ligado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a atividade da rede, incluindo emails, aplicações e Websites."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Está ligado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a atividade da rede pessoal, incluindo emails, aplicações e Websites."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Está ligado ao <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a atividade da rede pessoal, incluindo emails, aplicações e Websites."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"O seu perfil de trabalho é gerido por <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Está associado à aplicação <xliff:g id="APPLICATION">%2$s</xliff:g>, que pode monitorizar a sua atividade da rede de trabalho, incluindo emails, aplicações e Websites.\n\nPara obter mais informações, contacte o administrador."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"O seu perfil de trabalho é gerido por <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Está ligado a <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, que pode monitorizar a atividade da rede de trabalho, incluindo emails, aplicações e Websites.\n\nTambém está ligado a <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, que pode monitorizar a atividade da rede pessoal."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"O dispositivo permanecerá bloqueado até ser desbloqueado manualmente"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Receber notificações mais rapidamente"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index c89cdc9..7edebe0 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -323,12 +323,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Aviso de <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modo de trabalho"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Modo noturno"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"A NFC está desativada"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"A NFC está ativada"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nenhum item recente"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Você limpou tudo"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informações do app"</string>
@@ -342,16 +339,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divisão horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divisão vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divisão personalizada"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Dispensar"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Abrir"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Dividir a tela para a parte superior"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Dividir a tela para a esquerda"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Dividir a tela para a direita"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Carregada"</string>
@@ -432,24 +424,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Desconectar VPN"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Seu dispositivo é gerenciado por <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> usa <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> para gerenciar seu dispositivo."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"O admin. pode monitorar e gerenciar config., acesso corporativo, apps, dados associados ao dispos. e info de local do dispositivo."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Saber mais"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Você está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorar sua atividade na rede, incluindo e-mails, apps e websites."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Abrir configurações de VPN"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Seu administrador ativou o registro de rede, que monitora o tráfego no seu dispositivo.\n\nPara ver mais informações, entre em contato com o administrador."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Você deu permissão para um app configurar uma conexão VPN.\n\nEsse app pode monitorar seu dispositivo e a atividade na rede, incluindo e-mails, apps e websites."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Seu perfil de trabalho é gerenciado por <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nSeu administrador pode monitorar sua atividade de rede, incluindo e-mails, apps e websites.\n\nPara ver mais informações, entre em contato com o administrador.\n\nVocê também está conectado a uma VPN, que pode monitorar sua atividade de rede."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Você está conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorar sua atividade na rede, incluindo e-mails, apps e websites."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Você está conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorar sua atividade pessoal na rede, incluindo e-mails, apps e websites."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Você está conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorar sua atividade pessoal na rede, incluindo e-mails, apps e websites."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Seu perfil de trabalho é gerenciado por <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Ele está conectado ao app <xliff:g id="APPLICATION">%2$s</xliff:g>, que pode monitorar sua atividade profissional de rede, incluindo e-mails, apps e websites.\n\nPara ver mais informações, entre em contato com o administrador."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Seu perfil de trabalho é gerenciado por <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Ele está conectado a <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, que pode monitorar sua atividade profissional na rede, incluindo e-mails, apps e websites.\n\nVocê também está conectado a <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, que pode monitorar sua atividade pessoal na rede."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"O dispositivo permanecerá bloqueado até que você o desbloqueie manualmente"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Receba notificações mais rápido"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 66f7bde..0cfd530 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -325,12 +325,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Avertizare: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modul de lucru"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Lumină de noapte"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"Serviciul NFC este dezactivat"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"Serviciul NFC este activat"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Niciun element recent"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Ați șters tot"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informații despre aplicație"</string>
@@ -344,16 +341,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Divizare pe orizontală"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Divizare pe verticală"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Divizare personalizată"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Respingeți"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Deschideți"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Divizați ecranul în partea de sus"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Divizați ecranul la stânga"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Divizați ecranul la dreapta"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Încărcată"</string>
@@ -434,24 +426,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Deconectați rețeaua VPN"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Dispozitivul dvs. este gestionat de <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> folosește <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> pentru a vă gestiona dispozitivul."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"Admin. dvs. poate monit. și gest. set., accesul la niv. companiei, ap., datele asoc. cu disp. dvs. și info. despre locația disp."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Aflați mai multe"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"V-ați conectat la aplicația <xliff:g id="VPN_APP">%1$s</xliff:g>, care vă poate monitoriza activitatea în rețea, inclusiv e-mailurile, aplicațiile și site-urile accesate."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Deschideți Setări VPN"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administratorul dvs. a activat înregistrarea în jurnal pentru rețea, funcție ce monitorizează traficul de pe dispozitivul dvs.\n\nPentru mai multe informații, contactați administratorul."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Ați acordat unei aplicații permisiunea de a configura o conexiune VPN.\n\nAceastă aplicație poate monitoriza activitatea de pe dispozitiv și în rețea, inclusiv e-mailurile, aplicațiile și site-urile."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Profilul dvs. de serviciu este gestionat de <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministratorul dvs. vă poate monitoriza activitatea în rețea, inclusiv e-mailurile, aplicațiile și site-urile.\n\nPentru mai multe informații, contactați administratorul.\n\nDe asemenea, sunteți conectat(ă) la o rețea VPN care vă poate monitoriza activitatea în rețea."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Sunteți conectat(ă) la <xliff:g id="APPLICATION">%1$s</xliff:g>, care vă poate monitoriza activitatea în rețea, inclusiv e-mailurile, aplicațiile și site-urile."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Sunteți conectat(ă) la <xliff:g id="APPLICATION">%1$s</xliff:g>, care vă poate monitoriza activitatea în rețeaua personală, inclusiv e-mailurile, aplicațiile și site-urile."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"V-ați conectat la aplicația <xliff:g id="APPLICATION">%1$s</xliff:g>, care vă poate monitoriza activitatea personală în rețea, inclusiv e-mailurile, aplicațiile și site-urile accesate."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Profilul dvs. de serviciu este gestionat de <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Acesta este conectat la <xliff:g id="APPLICATION">%2$s</xliff:g>, care vă poate monitoriza activitatea în rețeaua de serviciu, inclusiv e-mailurile, aplicațiile și site-urile.\n\nPentru mai multe informații, contactați administratorul."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Profilul de serviciu este gestionat de <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Este conectat la <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, care vă poate monitoriza activitatea în rețeaua de serviciu, inclusiv e-mailurile, aplicațiile și site-urile.\n\nDe asemenea, sunteți conectat(ă) la <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, care vă poate monitoriza activitatea în rețeaua personală."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Dispozitivul va rămâne blocat până când îl deblocați manual"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Obțineți notificări mai rapid"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 0571e8d..0686ca6 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -327,12 +327,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Предупреждение: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Рабочий режим"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Ночной режим"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"Модуль NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"Модуль NFC отключен"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"Модуль NFC включен"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Недавних приложений нет"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Вы очистили всё"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Сведения о приложении"</string>
@@ -346,16 +343,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Закрыть"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Открыть"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Батарея заряжена"</string>
@@ -436,24 +428,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Отключить VPN"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Запущено приложение \"<xliff:g id="VPN_APP">%1$s</xliff:g>\". Оно может отслеживать ваши действия в сети, включая работу с электронной почтой, приложениями и сайтами."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Открыть настройки VPN"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Администратор включил ведение сетевого журнала, чтобы отслеживать трафик на вашем устройстве.\n\nДля получения подробной информации обращайтесь к администратору."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Вы разрешили приложению подключаться к сети VPN.\n\nОно может отслеживать ваши действия на устройстве и в Интернете, включая работу с электронной почтой, приложениями и веб-сайтами."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"Запущено приложение \"<xliff:g id="APPLICATION">%1$s</xliff:g>\", которое может отслеживать ваши действия в Интернете, включая работу с электронной почтой, приложениями и веб-сайтами."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Запущено приложение \"<xliff:g id="APPLICATION">%1$s</xliff:g>\", которое может отслеживать ваши действия в Интернете (выполняемые в личном профиле), включая работу с электронной почтой, приложениями и веб-сайтами."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Запущено приложение \"<xliff:g id="APPLICATION">%1$s</xliff:g>\", которое может отслеживать ваши действия в сети, включая работу с электронной почтой, приложениями и веб-сайтами."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Вашим корпоративным профилем управляет <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Приложение <xliff:g id="APPLICATION">%2$s</xliff:g> может отслеживать ваши действия в сети, включая работу с электронной почтой, приложениями и веб-сайтами.\n\nЗа подробностями обратитесь к своему администратору."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Вашим рабочим профилем управляет \"<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_disabled" msgid="7412534203633528135">"Устройство необходимо будет разблокировать вручную"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Быстрый доступ к уведомлениям"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 5987fe5..2c752f2 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -340,16 +340,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"අස් කරන්න"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"විවෘත"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"අරෝපිතයි"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 9ace153..4013f41 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -327,12 +327,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Upozornenie pri <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Pracovný režim"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Nočný režim"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC je deaktivované"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC je aktivované"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Žiadne nedávne položky"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Vymazali ste všetko"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informácie o aplikácii"</string>
@@ -346,16 +343,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Rozdeliť vodorovné"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Rozdeliť zvislé"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Rozdeliť vlastné"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Odmietnuť"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Otvoriť"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Rozdelená obrazovka hore"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Rozdelená obrazovka naľavo"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Rozdelená obrazovka napravo"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nabitá"</string>
@@ -436,24 +428,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Odpojiť sieť VPN"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Vaše zariadenie spravuje aplikácia <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> spravuje vaše zariadenie pomocou aplikácie <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g>."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"Správca môže sledovať a spravovať nastavenia, firemný prístup, aplikácie a údaje súvisiace s týmto zariadením vrátane informácií o polohe vášho zariadenia."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Ďalšie informácie"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Ste pripojený/-á k aplikácii <xliff:g id="VPN_APP">%1$s</xliff:g>, ktorá môže sledovať vašu aktivitu v sieti vrátane e-mailových správ, aplikácií a webových stránok."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Otvoriť Nastavenia pripojenia VPN"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Správca aktivoval zapisovanie do denníka siete, ktoré sleduje premávku na vašom zariadení.\n\nĎalšie informácie vám poskytne správca."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Určitej aplikácii ste udelili povolenie nastaviť pripojenie VPN.\n\nTáto aplikácia môže sledovať vaše zariadenie a aktivitu v sieti vrátane e-mailových správ, aplikácií a webových stránok."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Váš pracovný profil spravuje organizácia <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nSprávca môže sledovať vašu aktivitu v sieti vrátane e-mailov, aplikácií a webov.\n\nĎalšie informácie vám poskytne správca.\n\nMáte tiež aktívne pripojenie k sieti VPN, ktorá môže sledovať vašu aktivitu v rámci siete."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Ste pripojený/-á k aplikácii <xliff:g id="APPLICATION">%1$s</xliff:g>, ktorá môže sledovať vašu aktivitu v sieti vrátane e-mailových správ, aplikácií a webových stránok."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Ste pripojený/-á k aplikácii <xliff:g id="APPLICATION">%1$s</xliff:g>, ktorá môže sledovať vašu osobnú aktivitu v sieti vrátane e-mailových správ, aplikácií a webových stránok."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Ste pripojený/-á k aplikácii <xliff:g id="APPLICATION">%1$s</xliff:g>, ktorá môže sledovať vašu osobnú aktivitu v sieti vrátane e-mailových správ, aplikácií a webových stránok."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Váš pracovný profil spravuje organizácia <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Je pripojený k aplikácii <xliff:g id="APPLICATION">%2$s</xliff:g>, ktorá môže sledovať vašu pracovnú aktivitu v sieti vrátane e-mailových správ, aplikácií a webov.\n\nĎalšie informácie vám poskytne správca."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Váš pracovný profil spravuje organizácia <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Je pripojený k aplikácii <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, ktorá môže sledovať vašu pracovnú aktivitu v sieti vrátane e-mailových správ, aplikácií a webových stránok.\n\nSte tiež pripojený/-á k aplikácii <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, ktorá môže sledovať vašu osobnú aktivitu v sieti."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Zariadenie zostane uzamknuté, dokým ho ručne neodomknete."</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Získavať upozornenia rýchlejšie"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index ec26b53..9236970 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -346,16 +346,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Razdeli vodoravno"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Razdeli navpično"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Razdeli po meri"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Opusti"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Odpri"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Razdeljen zaslon na vrhu"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Razdeljen zaslon na levi"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Razdeljen zaslon na desni"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Akumulator napolnjen"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 009b0be..40b7c51d 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Paralajmërim për kufirin prej <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Modaliteti i punës"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Drita e natës"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC është çaktivizuar"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC është aktivizuar"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Nuk ka asnjë artikull të fundit"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"I ke pastruar të gjitha"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacioni i aplikacionit"</string>
@@ -340,16 +337,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Ndaje horizontalisht"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Ndaj vertikalisht"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Ndaj të personalizuarën"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Hiqe"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Hap"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Ndaje ekranin lart"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Ndaje ekranin në të majtë"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Ndaje ekranin në të djathtë"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"I ngarkuar"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Shkëput VPN-në"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Pajisja jote menaxhohet nga <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> përdor <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> për të menaxhuar pajisjen tënde."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"Administratori yt mund të monitorojë dhe të menaxhojë cilësimet, qasjen e korporatës, aplikacionet, të dhënat në lidhje me pajisjen si dhe informacionet e vendndodhjes së pajisjes tënde."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Mëso më shumë"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Je i lidhur me aplikacionin <xliff:g id="VPN_APP">%1$s</xliff:g>, i cili mund të monitorojë aktivitetin tënd në rrjet, duke përfshirë mail-et, aplikacionet dhe sajtet e uebit."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Hap cilësimet e VPN-së"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administratori yt ka aktivizuar regjistrimin e rrjetit, i cili monitoron trafikun në pajisjen tënde.\n\nPër më shumë informacione, kontakto me administratorin."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"I dhe leje një aplikacioni që të konfigurojë një lidhje VPN.\n\nKy aplikacion mund të monitorojë pajisjen tënde dhe aktivitetin e rrjetit, përfshirë mailet, aplikacionet dhe sajtet e uebit."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Profili yt i punës menaxhohet nga <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministratori yt mund të monitorojë aktivitetin tënd të rrjetit, duke përfshirë email-et, aplikacionet dhe sajtet e uebit.\n\nPër më shumë informacion, kontakto me administratorin tënd.\n\nJe i lidhur edhe me një VPN, që mund të monitorojë aktivitetin tënd të rrjetit."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Je i lidhur me aplikacionin <xliff:g id="APPLICATION">%1$s</xliff:g>, i cili mund të monitorojë aktivitetin tënd në rrjet përfshirë mailet, aplikacionet dhe sajtet e uebit."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Je i lidhur me aplikacionin <xliff:g id="APPLICATION">%1$s</xliff:g>, i cili mund të monitorojë aktivitetin tënd personal në rrjet, përfshirë mailet, aplikacionet dhe sajtet e uebit."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Je i lidhur me aplikacionin <xliff:g id="APPLICATION">%1$s</xliff:g>, i cili mund të monitorojë aktivitetin tënd personal në rrjet, përfshirë mailet, aplikacionet dhe sajtet e uebit."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Profili yt i punës menaxhohet nga <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Ai është i lidhur me <xliff:g id="APPLICATION">%2$s</xliff:g>, i cili mund të monitorojë aktivitetin tënd të punës në rrjet, përfshirë email-et, aplikacionet dhe sajtet e uebit.\n\nPër më shumë informacione, kontakto me administratorin tënd."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Profili yt i punës menaxhohet nga <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Ai është i lidhur me <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, i cili mund të monitorojë aktivitetin tënd të punës në rrjet, përfshirë mailet, aplikacionet dhe sajtet e uebit.\n\nJe lidhur gjithashtu edhe me <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, i cili mund të monitorojë aktivitetin tënd personal në rrjet."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Pajisje do të qëndrojë e kyçur derisa ta shkyçësh manualisht"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Merr njoftime më shpejt"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index a82ff68..d329f1b 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -323,12 +323,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Упозорење за <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Режим рада"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Ноћно светло"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC је онемогућен"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC је омогућен"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Нема недавних ставки"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Обрисали сте све"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Информације о апликацији"</string>
@@ -342,16 +339,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Одбаци"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Отвори"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Напуњена је"</string>
@@ -432,24 +424,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Прекини везу са VPN-ом"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Повезани сте са апликацијом <xliff:g id="VPN_APP">%1$s</xliff:g>, која може да надгледа активности на мрежи, укључујући имејлове, апликације и веб-сајтове."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Отворите подешавања VPN-а"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Администратор је укључио евидентирање мреже, које прати саобраћај на уређају.\n\nКонтактирајте администратора за више информација."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Дали сте дозволу апликацији да подешава VPN везу.\n\nТа апликација може да надгледа активности на уређају и мрежи, укључујући имејлове, апликације и веб-сајтове."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> управља профилом за Work.\n\nАдминистратор може да прати активности на мрежи, укључујући имејлове, апликације и веб-сајтове.\n\nКонтактирајте администратора за више информација.\n\nПовезани сте и са VPN-ом, који може да прати активности на мрежи."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Повезани сте са апликацијом <xliff:g id="APPLICATION">%1$s</xliff:g>, која може да надгледа активности на мрежи, укључујући имејлове, апликације и веб-сајтове."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Повезани сте са апликацијом <xliff:g id="APPLICATION">%1$s</xliff:g>, која може да надгледа активности на личној мрежи, укључујући имејлове, апликације и веб-сајтове."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Повезани сте са апликацијом <xliff:g id="APPLICATION">%1$s</xliff:g>, која може да надгледа активности на личној мрежи, укључујући имејлове, апликације и веб-сајтове."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> управља профилом за Work. Он је повезан са апликацијом <xliff:g id="APPLICATION">%2$s</xliff:g>, која може да прати активности на пословној мрежи, укључујући имејлове, апликације и веб-сајтове.\n\nКонтактирајте администратора за више информација."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Профилом за Work управља <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_disabled" msgid="7412534203633528135">"Уређај ће остати закључан док га не откључате ручно"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Брже добијајте обавештења"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 8c778d0..4b58ff9 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -340,16 +340,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Dela horisontellt"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Dela vertikalt"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Dela anpassad"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Ignorera"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Öppna"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Delad skärm till överkanten"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Delad skärm åt vänster"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Delad skärm åt höger"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Laddat"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 28ecc50..d8a4d42 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Onyo <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Hali ya kazi"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Mwanga wa Usiku"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC imezimwa"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC imewashwa"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Hakuna vipengee vya hivi karibuni"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Umeondoa vipengee vyote"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Maelezo ya Programu"</string>
@@ -340,16 +337,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Gawanya Mlalo"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Gawanya Wima"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Maalum Iliyogawanywa"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Ondoa"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Fungua"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Gawa skrini kuelekea juu"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Gawa skrini upande wa kushoto"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Gawa skrini upande wa kulia"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Betri imejaa"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Ondoa VPN"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Kifaa chako kinadhibitiwa na <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> inatumia <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> kudhibiti kifaa chako."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"Msimamizi wako anaweza kufuatilia na kudhibiti mipangilio, ufikiaji wa mashirika, programu, data inayohusiana na kifaa chako na maelezo ya eneo la kifaa chako."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Pata maelezo zaidi"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Umeunganishwa kwenye <xliff:g id="VPN_APP">%1$s</xliff:g>, ambayo inaweza kufuatilia shughuli za mtandao wako, ikiwa ni pamoja na barua pepe, programu na tovuti."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Fungua Mipangilio ya VPN"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Msimamizi wako amewasha kumbukumbu ya kuingia mtandaoni ambayo hufuatilia trafiki kwenye kifaa chako.\n\nKwa maelezo zaidi, wasiliana na msimamizi wako."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Uliruhusu programu iweke muunganisho wa VPN.\n\nProgramu hii inaweza kufuatilia shughuli za kifaa na mtandao wako, ikiwa ni pamoja na barua pepe, programu na tovuti."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Wasifu wako wa kazini unadhibitiwa na <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nMsimamizi wako anaweza kufuatilia shughuli za mtandaoni, ikiwa ni pamoja na barua pepe, programu na tovuti.\n\nKwa maelezo zaidi, wasiliana na msimamizi wako.\n\nUmeunganishwa pia kwenye VPN, ambayo inaweza kufuatilia shughuli zako mtandaoni."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Umeunganishwa kwenye <xliff:g id="APPLICATION">%1$s</xliff:g>, ambayo inaweza kufuatilia shughuli za mtandao wako, ikiwa ni pamoja na barua pepe, programu na tovuti."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Umeunganishwa kwenye <xliff:g id="APPLICATION">%1$s</xliff:g>, ambayo inaweza kufuatilia shughuli za mtandao wako, ikiwa ni pamoja na barua pepe, programu na tovuti."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Umeunganishwa kwenye <xliff:g id="APPLICATION">%1$s</xliff:g>, ambayo inaweza kufuatilia shughuli za mtandao wako, ikiwa ni pamoja na barua pepe, programu na tovuti."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Wasifu wako wa kazini unadhibitiwa na <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Umeunganishwa kwenye <xliff:g id="APPLICATION">%2$s</xliff:g>, ambayo inaweza kufuatilia shughuli zako za mtandao, ikiwa ni pamoja na barua pepe, programu na tovuti.\n\nKwa maelezo zaidi, wasiliana na msimamizi wako."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Wasifu wako wa kazini unasimamiwa na <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Wasifu huu umeunganishwa kwenye <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, ambayo inaweza kufuatilia mtandao wako wa kazini, ikiwa ni pamoja na barua pepe, programu na tovuti. \n\n Wewe pia umeunganishwa kwenye <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, ambayo inaweza kufuatilia shughuli za mtandao wako kibinafsi."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Kifaa kitaendelea kuwa katika hali ya kufungwa hadi utakapokifungua mwenyewe"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Pata arifa kwa haraka"</string>
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
index fd147cd..63b9d75 100644
--- a/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -34,7 +34,7 @@
     <bool name="config_keyguardUserSwitcher">true</bool>
 
     <!-- Nav bar button default ordering/layout -->
-    <string name="config_navBarLayout" translatable="false">space;back,home,recent;menu_ime</string>
+    <string name="config_navBarLayout" translatable="false">left;back,home,recent;right</string>
 
     <!-- Animation duration when using long press on recents to dock -->
     <integer name="long_press_dock_anim_duration">290</integer>
diff --git a/packages/SystemUI/res/values-sw900dp/config.xml b/packages/SystemUI/res/values-sw900dp/config.xml
index d8f9ef4..221b013 100644
--- a/packages/SystemUI/res/values-sw900dp/config.xml
+++ b/packages/SystemUI/res/values-sw900dp/config.xml
@@ -19,6 +19,6 @@
 <resources>
 
     <!-- Nav bar button default ordering/layout -->
-    <string name="config_navBarLayout" translatable="false">back,home;space;menu_ime,recent</string>
+    <string name="config_navBarLayout" translatable="false">back,home,left;space;right,recent</string>
 
 </resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 34daf43..5b17c54 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -340,16 +340,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"நிராகரி"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"திற"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"சார்ஜ் செய்யப்பட்டது"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 681bac2..701dc2d 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> హెచ్చరిక"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"పని మోడ్"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"రాత్రి కాంతి"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC నిలిపివేయబడింది"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC ప్రారంభించబడింది"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"ఇటీవలి అంశాలు ఏవీ లేవు"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"మీరు అన్నింటినీ తీసివేసారు"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"అనువర్తన సమాచారం"</string>
@@ -340,16 +337,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"తీసివేయి"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"తెరువు"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ఛార్జ్ చేయబడింది"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"VPNను డిస్‌కనెక్ట్ చేయి"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"మీరు <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఇమెయిల్‌లు, అనువర్తనాలు మరియు వెబ్‌సైట్‌లతో సహా మీ వ్యక్తిగత నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"VPN సెట్టింగ్‌లను తెరవండి"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"మీ నిర్వాహకులు మీ పరికరంలోని ట్రాఫిక్‌ని పర్యవేక్షించగల నెట్‌వర్క్ లాగింగ్‌ని ఆన్ చేసారు.\n\nమరింత సమాచారం కావాలంటే, మీ నిర్వాహకులను సంప్రదించండి."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"మీరు VPN కనెక్షన్ సెటప్ చేయడానికి ఒక అనువర్తనానికి అనుమతి ఇచ్చారు.\n\nఈ అనువర్తనం ఇమెయిల్‌లు, అనువర్తనాలు మరియు వెబ్‌సైట్‌లతో సహా మీ పరికరం మరియు నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"మీరు <xliff:g id="APPLICATION">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఇమెయిల్‌లు, అనువర్తనాలు మరియు వెబ్‌సైట్‌లతో సహా మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"మీరు <xliff:g id="APPLICATION">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఇమెయిల్‌లు, అనువర్తనాలు మరియు వెబ్‌‍సైట్‌లతో సహా మీ వ్యక్తిగత నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"మీరు <xliff:g id="APPLICATION">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఇమెయిల్‌లు, అనువర్తనాలు మరియు వెబ్‌సైట్‌లతో సహా మీ వ్యక్తిగత నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> ద్వారా మీ కార్యాలయ ప్రొఫైల్ నిర్వహించబడుతోంది. ఇది <xliff:g id="APPLICATION">%2$s</xliff:g>కు కనెక్ట్ చేయబడింది, ఇది ఇమెయిల్‌లు, అనువర్తనాలు మరియు వెబ్‌సైట్‌లతో సహా మీ కార్యాలయ నెట్‌వర్క్ కార్యాచరణను నిర్వహించగలదు.\n\nమరింత సమాచారం కావాలంటే, మీ నిర్వాహకులను సంప్రదించండి."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"మీ కార్యాలయ ప్రొఫైల్‌ను <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_disabled" msgid="7412534203633528135">"మీరు మాన్యువల్‌గా అన్‌లాక్ చేస్తే మినహా పరికరం లాక్ చేయబడి ఉంటుంది"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"నోటిఫికేషన్‌లను వేగంగా పొందండి"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 230c258..a051e3a 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"คำเตือน <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"โหมดการทำงาน"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"แสงตอนกลางคืน"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC ถูกปิดใช้งาน"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"เปิดใช้งาน NFC แล้ว"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"ไม่มีรายการล่าสุด"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"คุณได้ล้างทุกอย่างแล้ว"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"ข้อมูลแอปพลิเคชัน"</string>
@@ -340,16 +337,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"ปิด"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"เปิด"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"ชาร์จแล้ว"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"ยกเลิกการเชื่อมต่อ VPN"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"คุณเชื่อมต่อกับ <xliff:g id="VPN_APP">%1$s</xliff:g> ซึ่งสามารถตรวจสอบกิจกรรมในเครือข่ายของคุณ รวมถึงอีเมล แอป และเว็บไซต์ได้"</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"เปิดการตั้งค่า VPN"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"ผู้ดูแลระบบได้เปิดการทำบันทึกเครือข่าย ซึ่งจะติดตามดูการรับส่งข้อมูลบนอุปกรณ์ของคุณ\n\nโปรดติดต่อผู้ดูแลระบบสำหรับข้อมูลเพิ่มเติม"</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"คุณได้ให้สิทธิ์แอปในการตั้งค่าการเชื่อมต่อ VPN\n\nแอปนี้จะสามารถตรวจสอบอุปกรณ์และกิจกรรมในเครือข่าย รวมถึงอีเมล แอป และเว็บไซต์ได้"</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"คุณเชื่อมต่อกับ <xliff:g id="APPLICATION">%1$s</xliff:g> ซึ่งสามารถตรวจสอบกิจกรรมในเครือข่ายของคุณ รวมถึงอีเมล แอป และเว็บไซต์ได้"</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"คุณเชื่อมต่อกับ <xliff:g id="APPLICATION">%1$s</xliff:g> ซึ่งสามารถตรวจสอบกิจกรรมในเครือข่ายส่วนตัวของคุณ รวมถึงอีเมล แอป และเว็บไซต์ได้"</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"คุณเชื่อมต่อกับ <xliff:g id="APPLICATION">%1$s</xliff:g> ซึ่งสามารถตรวจสอบกิจกรรมในเครือข่ายส่วนตัวของคุณ รวมถึงอีเมล แอป และเว็บไซต์ได้"</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"โปรไฟล์งานของคุณได้รับการจัดการโดย <xliff:g id="ORGANIZATION">%1$s</xliff:g> โปรไฟล์ดังกล่าวเชื่อมโยงกับ <xliff:g id="APPLICATION">%2$s</xliff:g> ซึ่งสามารถตรวจสอบกิจกรรมในเครือข่ายงานของคุณ ซึ่งรวมถึงอีเมล แอป และเว็บไซต์ต่างๆ\n\nโปรดติดต่อผู้ดูแลระบบสำหรับข้อมูลเพิ่มเติม"</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"โปรไฟล์งานได้รับการจัดการโดย <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_disabled" msgid="7412534203633528135">"อุปกรณ์จะล็อกจนกว่าคุณจะปลดล็อกด้วยตนเอง"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"รับการแจ้งเตือนเร็วขึ้น"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 7bd443c..7857811 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -340,16 +340,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Split Horizontal"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Split Vertical"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Split Custom"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"I-dismiss"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Bukas"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"I-split ang screen pataas"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"I-split ang screen pakaliwa"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"I-split ang screen pakanan"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Nasingil na"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index f6b42c9..d4ef51d 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -340,16 +340,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Yatay Ayırma"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Dikey Ayırma"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Özel Ayırma"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Kapat"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Aç"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Ekranı yukarıya doğru böl"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Ekranı sola doğru böl"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Ekranı sağa doğru böl"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Ödeme alındı"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 5d58046..11f88c5 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -346,16 +346,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Закрити"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Відкрити"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Заряджено"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 53c67e7..f67ce8e 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> وارننگ"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"کام موڈ"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"نائٹ لائٹ"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"‏NFC غیر فعال ہے"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"‏NFC فعال ہے"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"کوئی حالیہ آئٹم نہیں"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"آپ نے سب کچھ صاف کر دیا ہے"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"ایپلیکیشن کی معلومات"</string>
@@ -430,24 +427,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"‏VPN کو غیر منسلک کریں"</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>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <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>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"آپ <xliff:g id="VPN_APP">%1$s</xliff:g> سے منسلک ہیں جو ای میلز، ایپس اور ویب سائٹس سمیت آپ کے نیٹ ورک کی سرگرمی مانیٹر کر سکتی ہے۔"</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"‏VPN کی ترتیبات کھولیں"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"آپ کے ایڈمن نے نیٹ ورک لاگنگ آن کر دی ہے، جو آپ کے آلہ پر ٹریفک کو مانیٹر کرتی ہے۔\n\nمزید معلومات کیلئے اپنے ایڈمن سے رابطہ کریں۔"</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"‏آپ نے ایک ایپ کو VPN کنکشن ترتیب دینے کی اجازت دی ہے۔\n\nیہ ایپ ای میلز، ایپس اور ویب سائٹس سمیت آپ کے آلہ اور نیٹ ورک کی سرگرمی مانیٹر کر سکتی ہے۔"</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <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="6259179342284742878">"آپ <xliff:g id="APPLICATION">%1$s</xliff:g> سے منسلک ہیں، جو ای میلز، ایپس اور ویب سائٹس سمیت آپ کے نیٹ ورک کی سرگرمی مانیٹر کر سکتی ہے۔"</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"آپ <xliff:g id="APPLICATION">%1$s</xliff:g> سے منسلک ہیں، جو آپ کے نجی نیٹ ورک کی سرگرمی سمیت ای میلز، ایپس اور ویب سائٹس مانیٹر کر سکتی ہے۔"</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"آپ <xliff:g id="APPLICATION">%1$s</xliff:g> سے منسلک ہیں، جو ای میلز، ایپس اور ویب سائٹس سمیت آپ کے نجی نیٹ ورک کی سرگرمی مانیٹر کر سکتی ہے۔"</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"آپ کی دفتری پروفائل <xliff:g id="ORGANIZATION">%1$s</xliff:g> کے زیر نظم ہے۔ یہ <xliff:g id="APPLICATION">%2$s</xliff:g> سے منسلک ہے، جو بشمول ای میلز، ایپس اور ویب سائٹس، آپ کے دفتری نیٹ ورک کی سرگرمی کو مانیٹر کر سکتی ہے۔ \n\nمزید معلومات کے لیے، اپنے ایڈمن سے رابطہ کریں۔"</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"آپ کا دفتری پروفائل <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_disabled" msgid="7412534203633528135">"آلہ اس وقت تک مقفل رہے گا جب تک آپ دستی طور پر اسے غیر مقفل نہ کریں"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"تیزی سے اطلاعات حاصل کریں"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 9ea82d6..cf4435f 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -323,12 +323,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Ogohlantirish: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Ish rejimi"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Tungi rejim"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC o‘chiq"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC yoniq"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Hozircha hech narsa yo‘q"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Hammasi o‘chirildi"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Ilova haqida ma’lumot"</string>
@@ -342,16 +339,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Gorizontal yo‘nalishda bo‘lish"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Vertikal yo‘nalishda bo‘lish"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Boshqa usulda bo‘lish"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Yopish"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Ochish"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Ekranni tepaga qadash"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Ekranni chap tomonga qadash"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Ekranni o‘ng tomonga qadash"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Batareya quvvati to‘ldi"</string>
@@ -432,24 +424,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"VPN ulanishini uzish"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Qurilmangiz <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g> tomonidan boshqariladi."</string>
     <string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> qurilmangizni boshqarish uchun <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> ilovasidan foydalanadi."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"Administratoringiz qurilmangiz bilan bog‘liq sozlamalar, korporativ kirish huquqi, ilova va ma’lumotlarni hamda qurilmangizning joylashuv axborotini kuzatishi va boshqarishi mumkin."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Batafsil"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"<xliff:g id="VPN_APP">%1$s</xliff:g> ilovasi ishga tushirilgan. U internetdagi harakatlaringiz, jumladan, e-pochta, ilova va veb-saytlardagi xatti-harakatlaringizni kuzatishi mumkin."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"VPN sozlamalarini ochish"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Administrator qurilmangizdagi trafikni nazorat qiluvchi tarmoq jurnalini yoqdi.\n\nBatafsil ma’lumot olish uchun administratoringizga murojaat qiling."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Siz ilovaga VPN tarmog‘iga ulanishga ruxsat bergansiz.\n\nUshbu ilova qurilmangiz va internetdagi harakatlaringizni, jumladan, e-pochta, ilovalar va veb-saytlardagi xatti-harakatlaringizni kuzatishi mumkin."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Sizning ishchi profilingiz <xliff:g id="ORGANIZATION">%1$s</xliff:g> tomonidan boshqariladi.\n\nAdministrator internetdagi harakatlaringizni, jumladan, e-pochta, ilova va xavfsiz veb-saytlar bilan ishlashingizni kuzatishi mumkin.\n\nBatafsil ma’lumot olish uchun administrator bilan bog‘laning.\n\nShuningdek, siz VPN tarmog‘iga ham ulangansiz. U internetdagi harakatlaringizni kuzatishi mumkin."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasi ishga tushirilgan. U internetdagi harakatlaringiz, jumladan, e-pochta, ilova va veb-saytlardagi xatti-harakatlaringizni kuzatishi mumkin."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasi ishga tushirilgan. U internetdagi harakatlaringiz, jumladan, e-pochta, ilova va veb-saytlardagi xatti-harakatlaringizni kuzatishi mumkin."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasi ishga tushirilgan. U internetdagi harakatlaringiz, jumladan, e-pochta, ilova va veb-saytlardagi xatti-harakatlaringizni kuzatishi mumkin."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Sizning ishchi profilingiz <xliff:g id="ORGANIZATION">%1$s</xliff:g> tomonidan boshqariladi. <xliff:g id="APPLICATION">%2$s</xliff:g> ilovasi ish tarmog‘idagi harakatlaringizni, jumladan, e-pochta, ilova va veb-saytlardagi xatti-harakatlaringizni kuzatishi mumkin.\n\nBatafsil ma’lumot olish uchun administrator bilan bog‘laning."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Sizning ishchi profilingiz <xliff:g id="ORGANIZATION">%1$s</xliff:g> tomonidan boshqariladi. <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> ilovasi ish tarmog‘idagi harakatlaringizni, jumladan, e-pochta, ilova va veb-saytlardagi xatti-harakatlaringizni kuzatishi mumkin.\n\nShuningdek, <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> ilovasi ham shaxsiy tarmoqdagi harakatlaringizni kuzatishi mumkin."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Qurilma qo‘lda qulfdan chiqarilmaguncha qulflangan holatda qoladi"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Bildirishnomalarni tezroq oling"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 6817871..d101ec1 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Cảnh báo <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Chế độ làm việc"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Đèn đọc sách"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"NFC đã được tắt"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"NFC đã được bật"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Không có mục gần đây nào"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Bạn đã xóa mọi nội dung"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Thông tin ứng dụng"</string>
@@ -340,16 +337,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Phân tách ngang"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Phân tách dọc"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Tùy chỉnh phân tách"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Loại bỏ"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Mở"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Chia đôi màn hình lên trên"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Chia đôi màn hình sang trái"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Chia đôi màn hình sang phải"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Đã sạc đầy"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Ngắt kết nối VPN"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Thiết bị của bạn do <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g> quản lý."</string>
     <string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> sử dụng <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> để quản lý thiết bị của bạn."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"Quản trị viên của bạn có thể giám sát và quản lý cài đặt, quyền truy cập dữ liệu công ty, ứng dụng, dữ liệu được liên kết với thiết bị và thông tin vị trí thiết bị của bạn."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Tìm hiểu thêm"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Bạn đang kết nối với <xliff:g id="VPN_APP">%1$s</xliff:g>. Ứng dụng này có thể giám sát hoạt động mạng của bạn, bao gồm email, ứng dụng và trang web."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Mở cài đặt VPN"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Quản trị viên đã bật tính năng ghi nhật ký mạng. Tính năng này giám sát lưu lượng truy cập trên thiết bị của bạn.\n\nĐể biết thêm thông tin, hãy liên hệ với quản trị viên của bạn."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Bạn đã cấp cho ứng dụng quyền thiết lập kết nối VPN.\n\nỨng dụng này có thể giám sát hoạt động mạng và thiết bị của bạn, bao gồm email, ứng dụng và trang web."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Hồ sơ công việc của bạn do <xliff:g id="ORGANIZATION">%1$s</xliff:g> quản lý.\n\nQuản trị viên có thể giám sát hoạt động mạng của bạn bao gồm email, ứng dụng và trang web.\n\nĐể biết thêm thông tin, hãy liên hệ với quản trị viên của bạn.\n\nBạn cũng được kết nối với VPN. Dịch vụ này có thể giám sát hoạt động mạng của bạn."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Bạn đang kết nối với <xliff:g id="APPLICATION">%1$s</xliff:g>. Ứng dụng này có thể giám sát hoạt động mạng của bạn bao gồm email, ứng dụng và trang web."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Bạn đang kết nối với <xliff:g id="APPLICATION">%1$s</xliff:g>. Ứng dụng này có thể giám sát hoạt động mạng cá nhân của bạn bao gồm email, ứng dụng và trang web."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Bạn đang kết nối với <xliff:g id="APPLICATION">%1$s</xliff:g>. Ứng dụng này có thể giám sát hoạt động mạng cá nhân của bạn bao gồm email, ứng dụng và trang web."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Hồ sơ công việc của bạn do <xliff:g id="ORGANIZATION">%1$s</xliff:g> quản lý. Hồ sơ này được kết nối với <xliff:g id="APPLICATION">%2$s</xliff:g>, ứng dụng này có thể giám sát hoạt động mạng của bạn, bao gồm email, ứng dụng và trang web.\n\nĐể biết thêm thông tin, hãy liên hệ với quản trị viên của bạn."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Hồ sơ công việc của bạn được quản lý bởi <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Hồ sơ được kết nối với <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, ứng dụng này có thể giám sát hoạt động mạng cơ quan của bạn, bao gồm email, ứng dụng và trang web.\n\nBạn cũng được kết nối với <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, có thể giám sát hoạt động mạng cá nhân của bạn."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Thiết bị sẽ vẫn bị khóa cho tới khi bạn mở khóa theo cách thủ công"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Nhận thông báo nhanh hơn"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 9e74d41..0392078 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -342,16 +342,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"關閉"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"開啟"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"已完成充電"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 1d52de3..1d7159a 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -340,16 +340,11 @@
     <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>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"關閉"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"開啟"</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>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"已充飽"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 0723e7e..7588eee 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -321,12 +321,9 @@
     <string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> isexwayiso"</string>
     <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Imodi yomsebenzi"</string>
     <string name="quick_settings_night_display_label" msgid="3577098011487644395">"Ukukhanya kwasebusuku"</string>
-    <!-- no translation found for quick_settings_nfc_label (9012153754816969325) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_off (6883274004315134333) -->
-    <skip />
-    <!-- no translation found for quick_settings_nfc_on (6680317193676884311) -->
-    <skip />
+    <string name="quick_settings_nfc_label" msgid="9012153754816969325">"I-NFC"</string>
+    <string name="quick_settings_nfc_off" msgid="6883274004315134333">"I-NFC ikhutshaziwe"</string>
+    <string name="quick_settings_nfc_on" msgid="6680317193676884311">"I-NFC inikwe amandla"</string>
     <string name="recents_empty_message" msgid="808480104164008572">"Azikho izinto zakamuva"</string>
     <string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Usule yonke into"</string>
     <string name="recents_app_info_button_label" msgid="2890317189376000030">"Ulwazi lohlelo lokusebenza"</string>
@@ -340,16 +337,11 @@
     <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Hlukanisa okuvundlile"</string>
     <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Hlukanisa okumile"</string>
     <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Hlukanisa kwezifiso"</string>
-    <!-- no translation found for recents_accessibility_dismissed (2354459747918667050) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_open (1651449827614876864) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_top (9056056469282256287) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_left (8987144699630620019) -->
-    <skip />
-    <!-- no translation found for recents_accessibility_split_screen_right (275069779299592867) -->
-    <skip />
+    <string name="recents_accessibility_dismissed" msgid="2354459747918667050">"Cashisa"</string>
+    <string name="recents_accessibility_open" msgid="1651449827614876864">"Kuvuliwe"</string>
+    <string name="recents_accessibility_split_screen_top" msgid="9056056469282256287">"Hlukanisela isikrini phezulu"</string>
+    <string name="recents_accessibility_split_screen_left" msgid="8987144699630620019">"Hlukanisela isikrini ngakwesokunxele"</string>
+    <string name="recents_accessibility_split_screen_right" msgid="275069779299592867">"Hlukanisela isikrini ngakwesokudla"</string>
   <string-array name="recents_blacklist_array">
   </string-array>
     <string name="expanded_header_battery_charged" msgid="5945855970267657951">"Kushajiwe"</string>
@@ -430,24 +422,20 @@
     <string name="disconnect_vpn" msgid="1324915059568548655">"Nqamula i-VPN"</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"Idivayisi yakho iphethwe yi-<xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g>."</string>
     <string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"I-<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> isebenzisa i-<xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> ukuze iphathe idivayisi yakho."</string>
-    <!-- no translation found for monitoring_description_do_body (3639594537660975895) -->
-    <skip />
+    <string name="monitoring_description_do_body" msgid="3639594537660975895">"Umlawuli wakho angaqaphela aphinde aphathe izilungiselelo, ukufinyelela kwezinkampani, izinhlelo zokusebenza, idatha ehlotshaniswa nedivayisi yakho, nolwazi lwendawo yedivayisi yakho."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Funda kabanzi"</string>
     <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Uxhumeke ku-<xliff:g id="VPN_APP">%1$s</xliff:g>, engaqapha umsebenzi wenethiwekhi yakho, ofaka ama-imeyili, izinhlelo zokusebenza, namawebhusayithi."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Vula izilungiselelo ze-VPN"</string>
-    <!-- no translation found for monitoring_description_network_logging (7223505523384076027) -->
-    <skip />
+    <string name="monitoring_description_network_logging" msgid="7223505523384076027">"Umlawuli wakho uvule ukungena kwenethiwekhi, okuhlola ithrafikhi kudivayisi yakho.\n\nNgolwazi olubanzi xhumana nomlawuli wakho."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Unikeze uhlelo lokusebenza imvume yokusetha ukuxhumana kwe-VPN.\n\nLolu hlelo lokusebenza lungahlola idivayisi yakho nomsebenzi wenethiwekhi, ofaka ama-imeyili, izinhlelo zokusebenza, namawebhusayithi."</string>
-    <!-- no translation found for monitoring_description_vpn_profile_owned (2958019119161161530) -->
-    <skip />
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"Iphrofayela yakho yomsebenzi iphethwe ngu-<xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nUmlawuli wakho uyakwazi ukwengamela umsebenzi wakho wenethiwekhi kufaka phakathi ama-imeyili, izinhlelo zokusebenza, namawebhusayithi.\n\nNgolwazi olubanzi, xhumana nomlawuli wakho.\n\nFuthi uxhumekile ku-VPN, engangamela umsebenzi wakho wenethiwekhi."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"I-VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Uxhumeke ku-<xliff:g id="APPLICATION">%1$s</xliff:g>, engahlola umsebenzi wakho wenethiwekhi ofaka ama-imeyili, izinhlelo zokusebenza, namawebhusayithi."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Uxhumeke ku-<xliff:g id="APPLICATION">%1$s</xliff:g>, engahlola umsebenzi wenethiwekhi yakho yomuntu siqu, ofaka ama-imeyili, izinhlelo zokusebenza, namawebhusayithi."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Uxhumeke ku-<xliff:g id="APPLICATION">%1$s</xliff:g>, engaqapha umsebenzi wakho womuntu siqu wenethiwekhi, ofaka ama-imeyili, izinhlelo zokusebenza, namawebhusayithi."</string>
-    <!-- no translation found for monitoring_description_app_work (7777228449969022305) -->
-    <skip />
+    <string name="monitoring_description_app_work" msgid="7777228449969022305">"Iphrofayela yakho yomsebenzi iphethwe ngu-<xliff:g id="ORGANIZATION">%1$s</xliff:g>. Ixhumeke ku-<xliff:g id="APPLICATION">%2$s</xliff:g>, engangamela umsebenzi wakho wenethiwekhi, kufaka phakathi ama-imeyili, izinhlelo zokusebenza, namawebhusayithi.\n\nNgolwazi olubanzi, xhumana nomlawuli wakho."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Iphrofayela yakho yomsebenzi iphethwe yi-<xliff:g id="ORGANIZATION">%1$s</xliff:g>. Ixhumeke ku-<xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, engahlola umsebenzi wenethiwekhi yakho yomsebenzi, ofaka ama-imeyili, izinhlelo zokusebenza namawebhusayithi.\n\nFuthi uxhumeke ku-<xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, engahlola umsebenzi wenethiwekhi yakho yomuntu siqu."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Idivayisi izohlala ikhiyekile uze uyivule ngokwenza"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Thola izaziso ngokushesha"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 3040814..1ec611a 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -103,6 +103,10 @@
     <color name="notification_guts_icon_tint">#8a000000</color>
     <color name="notification_guts_disabled_icon_tint">#4d000000</color>
 
+    <!-- Colors of the snooze menu reached via snooze icon behind a notification -->
+    <color name="snooze_snackbar_bg">#FF4A4A4A</color>
+	<color name="snooze_snackbar_text">#FFA6BAFF</color>
+
     <color name="assist_orb_color">#ffffff</color>
 
     <color name="keyguard_user_switcher_background_gradient_color">#77000000</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index d6ed9d8..2f39d1d 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -43,7 +43,7 @@
 
     <!-- Component to be used as the status bar service.  Must implement the IStatusBar
      interface.  This name is in the ComponentName flattened format (package/class)  -->
-    <string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.PhoneStatusBar</string>
+    <string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.StatusBar</string>
 
     <!-- Whether or not we show the number in the bar. -->
     <bool name="config_statusBarShowNumber">false</bool>
@@ -286,7 +286,7 @@
     <string name="config_systemUIFactoryComponent" translatable="false">com.android.systemui.SystemUIFactory</string>
 
     <!-- Nav bar button default ordering/layout -->
-    <string name="config_navBarLayout" translatable="false">space,back;home;recent,menu_ime</string>
+    <string name="config_navBarLayout" translatable="false">left,back;home;recent,right</string>
 
     <bool name="quick_settings_show_full_alarm">false</bool>
 
@@ -301,7 +301,5 @@
     <item type="id" name="action_split_task_to_left" />
     <item type="id" name="action_split_task_to_right" />
     <item type="id" name="action_split_task_to_top" />
-    <item type="id" name="action_open" />
-    <item type="id" name="action_dimiss" />
 
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 79529a7..ddcc4ba 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -106,11 +106,20 @@
     <!-- Minimum layouted height of a notification in the statusbar-->
     <dimen name="min_notification_layout_height">48dp</dimen>
 
-    <!-- Width of the space containing the gear icon behind a notification -->
-    <dimen name="notification_gear_width">64dp</dimen>
+    <!-- Size of the space to place a notification menu item -->
+    <dimen name="notification_menu_icon_size">64dp</dimen>
 
-    <!-- The space around the gear icon displayed behind a notification  -->
-    <dimen name="notification_gear_padding">20dp</dimen>
+    <!-- The space around a notification menu item  -->
+    <dimen name="notification_menu_icon_padding">20dp</dimen>
+
+    <!-- The minimum height for the snackbar shown after the snooze option has been chosen. -->
+    <dimen name="snooze_snackbar_min_height">48dp</dimen>
+
+    <!-- The text size of options in the snooze menu. -->
+    <dimen name="snooze_option_text_size">14sp</dimen>
+
+    <!-- The padding around options int the snooze menu. -->
+    <dimen name="snooze_option_padding">8dp</dimen>
 
     <!-- size at which Notification icons will be drawn in the status bar -->
     <dimen name="status_bar_icon_drawing_size">17dp</dimen>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 4a19dde..fc0c82c 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -58,7 +58,6 @@
     <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="custom_background_color"/>
 
     <!-- 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/strings.xml b/packages/SystemUI/res/values/strings.xml
index 422431e..d3e965a 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -794,10 +794,6 @@
     <string name="recents_multistack_add_stack_dialog_split_vertical">Split Vertical</string>
     <!-- Recents: MultiStack add stack split custom radio button. [CHAR LIMIT=NONE] -->
     <string name="recents_multistack_add_stack_dialog_split_custom">Split Custom</string>
-    <!-- Recents: Accessibility dismiss label -->
-    <string name="recents_accessibility_dismissed">Dismiss</string>
-    <!-- Recents: Accessibility open label -->
-    <string name="recents_accessibility_open">Open</string>
     <!-- Recents: Accessibility split to the top -->
     <string name="recents_accessibility_split_screen_top">Split screen to the top</string>
     <!-- Recents: Accessibility split to the left -->
@@ -1375,8 +1371,28 @@
     <!-- Notification: Control panel: Label for button that dismisses control panel. [CHAR LIMIT=NONE] -->
     <string name="notification_done">Done</string>
 
-    <!-- Notification: Gear: Content description for the gear. [CHAR LIMIT=NONE] -->
-    <string name="notification_gear_accessibility"><xliff:g id="app_name" example="YouTube">%1$s</xliff:g> notification controls</string>
+    <!-- Notification: Menu row: Content description for menu items. [CHAR LIMIT=NONE] -->
+    <string name="notification_menu_accessibility"><xliff:g id="app_name" example="YouTube">%1$s</xliff:g> <xliff:g id="menu_description" example="notification controls">%2$s</xliff:g></string>
+
+    <!-- Notification: Menu row: Content description for the gear menu item. [CHAR LIMIT=NONE] -->
+    <string name="notification_menu_gear_description">notification controls</string>
+
+    <!-- Notification: Menu row: Content description for the snooze icon. [CHAR LIMIT=NONE] -->
+    <string name="notification_menu_snooze_description">notification snooze options</string>
+
+    <!-- Notification: Menu row: Snooze options: 15 minute option. [CHAR LIMIT=50]-->
+    <string name="snooze_option_15_min">15 minutes</string>
+    <!-- Notification: Menu row: Snooze options: 30 minute option. [CHAR LIMIT=50]-->
+    <string name="snooze_option_30_min">30 minutes</string>
+    <!-- Notification: Menu row: Snooze options: 1 hour option. [CHAR LIMIT=50]-->
+    <string name="snooze_option_1_hour">1 hour</string>
+    <!-- Notification: Menu row: Snooze options: don't snooze option. [CHAR LIMIT=50] -->
+    <string name="snooze_option_dont_snooze">Don\'t snooze</string>
+    <!-- Notification: Menu row: Snooze undo button label. [CHAR LIMIT=50]-->
+    <string name="snooze_undo">UNDO</string>
+
+    <!-- Notification: Menu row: Snooze: message indicating how long the notification was snoozed for. [CHAR LIMIT=100]-->
+    <string name="snoozed_for_time">Snoozed for <xliff:g id="time_amount" example="15 minutes">%1$s</xliff:g></string>
 
     <!-- Title of the battery settings detail panel [CHAR LIMIT=20] -->
     <string name="battery_panel_title">Battery usage</string>
@@ -1523,56 +1539,71 @@
     <!-- SysUI Tuner: Button that leads to the navigation bar customization screen [CHAR LIMIT=60] -->
     <string name="nav_bar">Navigation bar</string>
 
-    <!-- SysUI Tuner: Group of buttons that show on the start of the screen [CHAR LIMIT=30] -->
-    <string name="start">Start</string>
-    <!-- SysUI Tuner: Group of buttons that show on the center of the screen [CHAR LIMIT=30] -->
-    <string name="center">Center</string>
-    <!-- SysUI Tuner: Group of buttons that show on the end of the screen [CHAR LIMIT=30] -->
-    <string name="end">End</string>
-    <!-- SysUI Tuner: Name of space used in custom navigation bar layouts [CHAR LIMIT=30] -->
-    <string name="space">Spacer</string>
+    <!-- SysUI Tuner: Button that controls layout of navigation bar [CHAR LIMIT=60] -->
+    <string name="nav_bar_layout">Layout</string>
+
+    <!-- SysUI Tuner: Label for section of settings about the left nav button [CHAR LIMIT=60] -->
+    <string name="nav_bar_left">Left</string>
+
+    <!-- SysUI Tuner: Label for section of settings about the right nav button [CHAR LIMIT=60] -->
+    <string name="nav_bar_right">Right</string>
+
+    <!-- SysUI Tuner: Setting for button type in nav bar [CHAR LIMIT=60] -->
+    <string name="nav_bar_button_type">Button type</string>
+
+    <!-- SysUI Tuner: Added to nav bar option to indicate it is the default [CHAR LIMIT=60] -->
+    <string name="nav_bar_default"> (default)</string>
+
+    <!-- SysUI Tuner: Labels for different types of navigation bar buttons [CHAR LIMIT=60] -->
+    <string-array name="nav_bar_buttons">
+        <item>Clipboard</item>
+        <item>Keycode</item>
+        <item>Menu / Keyboard Switcher</item>
+        <item>None</item>
+    </string-array>
+    <string-array name="nav_bar_button_values" translatable="false">
+        <item>clipboard</item>
+        <item>key</item>
+        <item>menu_ime</item>
+        <item>space</item>
+    </string-array>
+
+    <!-- SysUI Tuner: Labels for different types of navigation bar layouts [CHAR LIMIT=60] -->
+    <string-array name="nav_bar_layouts">
+        <item>Divided (default)</item>
+        <item>Centered</item>
+        <item>Left-aligned</item>
+        <item>Right-aligned</item>
+    </string-array>
+
+    <string-array name="nav_bar_layouts_values" translatable="false">
+        <item>default</item>
+        <item>left;back,home,recent;right</item>
+        <item>left,back,home,recent,right;space;space</item>
+        <item>space;space;left,back,home,recent,right</item>
+    </string-array>
+
     <!-- SysUI Tuner: Name of Combination Menu / Keyboard Switcher button [CHAR LIMIT=30] -->
     <string name="menu_ime">Menu / Keyboard Switcher</string>
-    <!-- SysUI Tuner: Title for dialog to add a button [CHAR LIMIT=30] -->
-    <string name="select_button">Select button to add</string>
-    <!-- SysUI Tuner: Button to add a button [CHAR LIMIT=30] -->
-    <string name="add_button">Add button</string>
     <!-- SysUI Tuner: Save the current settings [CHAR LIMIT=30] -->
     <string name="save">Save</string>
     <!-- SysUI Tuner: Reset to default settings [CHAR LIMIT=30] -->
     <string name="reset">Reset</string>
 
-    <!-- SysUI Tuner: Title of no home warning dialog [CHAR LIMIT=30] -->
-    <string name="no_home_title">No home button found</string>
-    <!-- SysUI Tuner: Message of no home warning dialog [CHAR LIMIT=NONE] -->
-    <string name="no_home_message">A home button is required to be able to navigate this device. Please add a home button before saving.</string>
-
     <!-- SysUI Tuner: Adjust button width dialog title [CHAR LIMIT=60] -->
     <string name="adjust_button_width">Adjust button width</string>
 
     <!-- SysUI Tuner: Nav bar button that holds the clipboard [CHAR LIMIT=30] -->
     <string name="clipboard">Clipboard</string>
 
-    <!-- SysUI Tuner: Description of nav bar button that holds the clipboard [CHAR LIMIT=NONE] -->
-    <string name="clipboard_description">The Clipboard allows items to be dragged directly to the clipboard. Items can also be dragged directly out of the clipboard when present.</string>
-
     <!-- SysUI Tuner: Accessibility description for custom nav key [CHAR LIMIT=NONE] -->
     <string name="accessibility_key">Custom navigation button</string>
 
     <!-- SysUI Tuner: Nav bar button that emulates a keycode [CHAR LIMIT=30] -->
     <string name="keycode">Keycode</string>
 
-    <!-- SysUI Tuner: Description of nav bar button that emulates a keycode [CHAR LIMIT=NONE] -->
-    <string name="keycode_description">Keycode buttons allow keyboard keys to
-        be added to the Navigation Bar. When pressed they emulate the selected
-        keyboard key. First the key must be selected for the button, followed
-        by an image to be shown on the button.</string>
-
-    <!-- SysUI Tuner: Title of dialog to select which key to emulate [CHAR LIMIT=60] -->
-    <string name="select_keycode">Select Keyboard Button</string>
-
-    <!-- SysUI Tuner: Label for preview area in navigation bar tuner [CHAR LIMIT=NONE] -->
-    <string name="preview">Preview</string>
+    <!-- SysUI Tuner: Settings to change nav bar icon [CHAR LIMIT=30] -->
+    <string name="icon">Icon</string>
 
     <!-- Label for area where tiles can be dragged out of [CHAR LIMIT=60] -->
     <string name="drag_to_add_tiles">Drag to add tiles</string>
@@ -1752,5 +1783,30 @@
     <!-- Text body for dialog alerting user that their phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=300] -->
     <string name="high_temp_dialog_message">Your phone will automatically try to cool down. You can still use your phone, but it may run slower.\n\nOnce your phone has cooled down, it will run normally.</string>
 
+    <!-- SysUI Tuner: Group of settings for left lock screen affordance [CHAR LIMIT=60] -->
+    <string name="lockscreen_left">Left</string>
+
+    <!-- SysUI Tuner: Group of settings for right lock screen affordance [CHAR LIMIT=60] -->
+    <string name="lockscreen_right">Right</string>
+
+    <!-- SysUI Tuner: Switch controlling whether to customize lock screen button [CHAR LIMIT=60] -->
+    <string name="lockscreen_customize">Customize shortcut</string>
+
+    <!-- SysUI Tuner: Button to select lock screen shortcut [CHAR LIMIT=60] -->
+    <string name="lockscreen_shortcut">Shortcut</string>
+
+    <!-- SysUI Tuner: Switch to control if device gets unlocked [CHAR LIMIT=60] -->
+    <string name="lockscreen_unlock">Prompt for password</string>
+
+    <!-- Title for the notification channel containing important alerts like low battery. [CHAR LIMIT=NONE] -->
+    <string name="notification_channel_alerts">Alerts</string>
+    <!-- Title for the notification channel dedicated to screenshot progress. [CHAR LIMIT=NONE] -->
+    <string name="notification_channel_screenshot">Screenshots</string>
+    <!-- Title for the notification channel for urgent security issues. [CHAR LIMIT=NONE] -->
+    <string name="notification_channel_security">Security</string>
+    <!-- Title for the notification channel containing multi-user status information. [CHAR LIMIT=NONE] -->
+    <string name="notification_channel_user_status">User status</string>
+    <!-- Title for the notification channel for problems with storage (i.e. low disk). [CHAR LIMIT=NONE] -->
+    <string name="notification_channel_storage">Storage</string>
 
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 6535a81..c5a5518 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -383,6 +383,20 @@
         <item name="android:textColor">?android:attr/colorAccent</item>
     </style>
 
+    <style name="TextAppearance.SnoozeSnackBar">
+        <item name="android:textSize">14sp</item>
+        <item name="android:fontFamily">roboto-regular</item>
+        <item name="android:textColor">@android:color/white</item>
+    </style>
+
+    <style name="TextAppearance.SnoozeSnackBar.Button">
+        <item name="android:textSize">14sp</item>
+        <item name="android:textAllCaps">true</item>
+        <item name="android:fontFamily">sans-serif-medium</item>
+        <item name="android:gravity">center</item>
+        <item name="android:textColor">@color/snooze_snackbar_text</item>
+    </style>
+
     <style name="edit_theme" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
         <item name="android:colorBackground">?android:attr/colorSecondary</item>
     </style>
diff --git a/packages/SystemUI/res/xml/lockscreen_settings.xml b/packages/SystemUI/res/xml/lockscreen_settings.xml
new file mode 100644
index 0000000..73e29af
--- /dev/null
+++ b/packages/SystemUI/res/xml/lockscreen_settings.xml
@@ -0,0 +1,59 @@
+<?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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:sysui="http://schemas.android.com/apk/res-auto"
+    android:title="@string/other">
+
+    <PreferenceCategory
+        android:key="left"
+        android:title="@string/lockscreen_left">
+
+        <SwitchPreference
+            android:key="customize"
+            android:title="@string/lockscreen_customize" />
+
+        <Preference
+            android:key="shortcut"
+            android:title="@string/lockscreen_shortcut" />
+
+        <com.android.systemui.tuner.TunerSwitch
+            android:key="sysui_keyguard_left_unlock"
+            android:title="@string/lockscreen_unlock"
+            sysui:defValue="true" />
+
+    </PreferenceCategory>
+
+    <PreferenceCategory
+        android:key="right"
+        android:title="@string/lockscreen_right">
+
+        <SwitchPreference
+            android:key="customize"
+            android:title="@string/lockscreen_customize" />
+
+        <Preference
+            android:key="shortcut"
+            android:title="@string/lockscreen_shortcut" />
+
+        <com.android.systemui.tuner.TunerSwitch
+            android:key="sysui_keyguard_right_unlock"
+            android:title="@string/lockscreen_unlock"
+            sysui:defValue="true" />
+
+    </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/packages/SystemUI/res/xml/nav_bar_tuner.xml b/packages/SystemUI/res/xml/nav_bar_tuner.xml
new file mode 100644
index 0000000..6fa8bec
--- /dev/null
+++ b/packages/SystemUI/res/xml/nav_bar_tuner.xml
@@ -0,0 +1,79 @@
+<?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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:sysui="http://schemas.android.com/apk/res-auto"
+    android:title="@string/nav_bar">
+
+    <ListPreference
+        android:key="layout"
+        android:title="@string/nav_bar_layout"
+        android:summary="%s"
+        android:persistent="false"
+        android:entries="@array/nav_bar_layouts"
+        android:entryValues="@array/nav_bar_layouts_values" />
+
+    <PreferenceCategory
+        android:key="left"
+        android:title="@string/nav_bar_left">
+
+        <DropDownPreference
+            android:key="type_left"
+            android:title="@string/nav_bar_button_type"
+            android:persistent="false"
+            android:summary="%s"
+            android:entries="@array/nav_bar_buttons"
+            android:entryValues="@array/nav_bar_button_values" />
+
+        <Preference
+            android:key="keycode_left"
+            android:persistent="false"
+            android:title="@string/keycode" />
+
+        <com.android.systemui.tuner.BetterListPreference
+            android:key="icon_left"
+            android:persistent="false"
+            android:summary="%s"
+            android:title="@string/icon" />
+
+    </PreferenceCategory>
+
+    <PreferenceCategory
+        android:key="right"
+        android:title="@string/nav_bar_right">
+
+        <DropDownPreference
+            android:key="type_right"
+            android:title="@string/nav_bar_button_type"
+            android:summary="%s"
+            android:persistent="false"
+            android:entries="@array/nav_bar_buttons"
+            android:entryValues="@array/nav_bar_button_values" />
+
+        <Preference
+            android:key="keycode_right"
+            android:persistent="false"
+            android:title="@string/keycode" />
+
+        <com.android.systemui.tuner.BetterListPreference
+            android:key="icon_right"
+            android:persistent="false"
+            android:summary="%s"
+            android:title="@string/icon" />
+
+    </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 59a10da..94a7c07 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -150,12 +150,15 @@
 
     </PreferenceScreen>
 
-    <!--
     <Preference
         android:key="nav_bar"
         android:title="@string/nav_bar"
         android:fragment="com.android.systemui.tuner.NavBarTuner" />
-    -->
+
+    <Preference
+            android:key="lockscreen"
+            android:title="@string/accessibility_desc_lock_screen"
+            android:fragment="com.android.systemui.tuner.LockscreenFragment" />
 
     <Preference
             android:key="other"
diff --git a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
index 4ae81a7..14c67fe 100644
--- a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
@@ -19,7 +19,7 @@
 
 /**
  * Single common instance of ActivityStarter that can be gotten and referenced from anywhere, but
- * delegates to an actual implementation such as PhoneStatusBar, assuming it exists.
+ * delegates to an actual implementation such as StatusBar, assuming it exists.
  */
 public class ActivityStarterDelegate implements ActivityStarter {
 
diff --git a/packages/SystemUI/src/com/android/systemui/LatencyTester.java b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
index c14b17f..1d55ee5 100644
--- a/packages/SystemUI/src/com/android/systemui/LatencyTester.java
+++ b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
@@ -27,7 +27,7 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.LatencyTracker;
 import com.android.systemui.statusbar.phone.FingerprintUnlockController;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.StatusBar;
 
 /**
  * Class that only runs on debuggable builds that listens to broadcasts that simulate actions in the
@@ -72,7 +72,7 @@
     }
 
     private void fakeWakeAndUnlock() {
-        FingerprintUnlockController fingerprintUnlockController = getComponent(PhoneStatusBar.class)
+        FingerprintUnlockController fingerprintUnlockController = getComponent(StatusBar.class)
                 .getFingerprintUnlockController();
         fingerprintUnlockController.onFingerprintAcquired();
         fingerprintUnlockController.onFingerprintAuthenticated(
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 5c50b5c..a95713f 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -32,7 +32,9 @@
 import android.view.accessibility.AccessibilityEvent;
 
 import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.MenuItem;
 import com.android.systemui.statusbar.FlingAnimationUtils;
+import com.android.systemui.statusbar.NotificationMenuRow;
 
 import java.util.HashMap;
 
@@ -85,10 +87,12 @@
     private int mFalsingThreshold;
     private boolean mTouchAboveFalsingThreshold;
     private boolean mDisableHwLayers;
+    private Context mContext;
 
     private HashMap<View, Animator> mDismissPendingMap = new HashMap<>();
 
     public SwipeHelper(int swipeDirection, Callback callback, Context context) {
+        mContext = context;
         mCallback = callback;
         mHandler = new Handler();
         mSwipeDirection = swipeDirection;
@@ -249,6 +253,7 @@
         }
     }
 
+    @Override
     public boolean onInterceptTouchEvent(final MotionEvent ev) {
         final int action = ev.getAction();
 
@@ -280,7 +285,8 @@
                                         mCurrView.getLocationOnScreen(mTmpPos);
                                         final int x = (int) ev.getRawX() - mTmpPos[0];
                                         final int y = (int) ev.getRawY() - mTmpPos[1];
-                                        mLongPressListener.onLongPress(mCurrView, x, y);
+                                        mLongPressListener.onLongPress(mCurrView, x, y,
+                                                NotificationMenuRow.getLongpressMenuItem(mContext));
                                     }
                                 }
                             };
@@ -379,6 +385,7 @@
             animView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
         }
         AnimatorUpdateListener updateListener = new AnimatorUpdateListener() {
+            @Override
             public void onAnimationUpdate(ValueAnimator animation) {
                 onTranslationUpdate(animView, (float) animation.getAnimatedValue(), canBeDismissed);
             }
@@ -401,10 +408,12 @@
         anim.addListener(new AnimatorListenerAdapter() {
             private boolean mCancelled;
 
+            @Override
             public void onAnimationCancel(Animator animation) {
                 mCancelled = true;
             }
 
+            @Override
             public void onAnimationEnd(Animator animation) {
                 updateSwipeProgressFromOffset(animView, canBeDismissed);
                 mDismissPendingMap.remove(animView);
@@ -435,6 +444,7 @@
     public void snapChild(final View animView, final float targetLeft, float velocity) {
         final boolean canBeDismissed = mCallback.canChildBeDismissed(animView);
         AnimatorUpdateListener updateListener = new AnimatorUpdateListener() {
+            @Override
             public void onAnimationUpdate(ValueAnimator animation) {
                 onTranslationUpdate(animView, (float) animation.getAnimatedValue(), canBeDismissed);
             }
@@ -447,6 +457,7 @@
         int duration = SNAP_ANIM_LEN;
         anim.setDuration(duration);
         anim.addListener(new AnimatorListenerAdapter() {
+            @Override
             public void onAnimationEnd(Animator animator) {
                 mSnappingChild = false;
                 updateSwipeProgressFromOffset(animView, canBeDismissed);
@@ -522,6 +533,7 @@
         }
     }
 
+    @Override
     public boolean onTouchEvent(MotionEvent ev) {
         if (mLongPressSent) {
             return true;
@@ -690,6 +702,6 @@
          * Equivalent to {@link View.OnLongClickListener#onLongClick(View)} with coordinates
          * @return whether the longpress was handled
          */
-        boolean onLongPress(View v, int x, int y);
+        boolean onLongPress(View v, int x, int y, MenuItem item);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java b/packages/SystemUI/src/com/android/systemui/SystemBars.java
similarity index 80%
rename from packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java
rename to packages/SystemUI/src/com/android/systemui/SystemBars.java
index 275fd70..6623cabe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemBars.java
@@ -1,20 +1,18 @@
 /*
- * Copyright (C) 2013 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.
- * You may obtain a copy of the License at
+ * 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.
+ * 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;
+package com.android.systemui;
 
 import android.content.res.Configuration;
 import android.provider.Settings;
@@ -36,7 +34,7 @@
     private static final int WAIT_FOR_BARS_TO_DIE = 500;
 
     // in-process fallback implementation, per the product config
-    private BaseStatusBar mStatusBar;
+    private SystemUI mStatusBar;
 
     @Override
     public void start() {
@@ -71,7 +69,7 @@
             throw andLog("Error loading status bar component: " + clsName, t);
         }
         try {
-            mStatusBar = (BaseStatusBar) cls.newInstance();
+            mStatusBar = (SystemUI) cls.newInstance();
         } catch (Throwable t) {
             throw andLog("Error creating status bar component: " + clsName, t);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index f2aaec1..9515585 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -42,10 +42,10 @@
 import com.android.systemui.shortcut.ShortcutKeyDispatcher;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.SystemBars;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.usb.StorageNotification;
+import com.android.systemui.util.NotificationChannels;
 import com.android.systemui.volume.VolumeUI;
 
 import java.util.HashMap;
@@ -66,6 +66,7 @@
             Dependency.class,
             FragmentService.class,
             TunerService.class,
+            NotificationChannels.class,
             CommandQueue.CommandQueueStart.class,
             KeyguardViewMediator.class,
             Recents.class,
@@ -208,10 +209,10 @@
                 new PluginListener<OverlayPlugin>() {
             @Override
             public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
-                PhoneStatusBar phoneStatusBar = getComponent(PhoneStatusBar.class);
-                if (phoneStatusBar != null) {
-                    plugin.setup(phoneStatusBar.getStatusBarWindow(),
-                            phoneStatusBar.getNavigationBarView());
+                StatusBar statusBar = getComponent(StatusBar.class);
+                if (statusBar != null) {
+                    plugin.setup(statusBar.getStatusBarWindow(),
+                            statusBar.getNavigationBarView());
                 }
             }
         }, OverlayPlugin.VERSION, true /* Allow multiple plugins */);
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index ec11812..1ff0701 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -26,10 +26,7 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.Dependency.DependencyProvider;
-import com.android.systemui.R;
-import com.android.systemui.assist.AssistManager;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
-import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.KeyguardIndicationController;
 import com.android.systemui.statusbar.ScrimView;
 import com.android.systemui.statusbar.phone.KeyguardBouncer;
@@ -37,26 +34,11 @@
 import com.android.systemui.statusbar.phone.LockIcon;
 import com.android.systemui.statusbar.phone.LockscreenWallpaper;
 import com.android.systemui.statusbar.phone.NotificationIconAreaController;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.QSTileHost;
 import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
-import com.android.systemui.statusbar.phone.StatusBarWindowManager;
-import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.BluetoothController;
-import com.android.systemui.statusbar.policy.CastController;
-import com.android.systemui.statusbar.policy.FlashlightController;
-import com.android.systemui.statusbar.policy.HotspotController;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
-import com.android.systemui.statusbar.policy.LocationController;
-import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.NextAlarmController;
-import com.android.systemui.statusbar.policy.RotationLockController;
-import com.android.systemui.statusbar.policy.SecurityController;
-import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.statusbar.policy.ZenModeController;
 import com.android.systemui.volume.VolumeDialogController;
 
 /**
@@ -113,8 +95,8 @@
     }
 
     public NotificationIconAreaController createNotificationIconAreaController(Context context,
-            PhoneStatusBar phoneStatusBar) {
-        return new NotificationIconAreaController(context, phoneStatusBar);
+            StatusBar statusBar) {
+        return new NotificationIconAreaController(context, statusBar);
     }
 
     public KeyguardIndicationController createKeyguardIndicationController(Context context,
@@ -122,7 +104,7 @@
         return new KeyguardIndicationController(context, indicationArea, lockIcon);
     }
 
-    public QSTileHost createQSTileHost(Context context, PhoneStatusBar statusBar,
+    public QSTileHost createQSTileHost(Context context, StatusBar statusBar,
             StatusBarIconController iconController) {
         return new QSTileHost(context, statusBar, iconController);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index ce89aab..99c8c6b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -80,7 +80,7 @@
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.statusbar.phone.FingerprintUnlockController;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.phone.StatusBarWindowManager;
@@ -1955,11 +1955,11 @@
         Trace.endSection();
     }
 
-    public StatusBarKeyguardViewManager registerStatusBar(PhoneStatusBar phoneStatusBar,
+    public StatusBarKeyguardViewManager registerStatusBar(StatusBar statusBar,
             ViewGroup container, StatusBarWindowManager statusBarWindowManager,
             ScrimController scrimController,
             FingerprintUnlockController fingerprintUnlockController) {
-        mStatusBarKeyguardViewManager.registerStatusBar(phoneStatusBar, container,
+        mStatusBarKeyguardViewManager.registerStatusBar(statusBar, container,
                 statusBarWindowManager, scrimController, fingerprintUnlockController,
                 mDismissCallbackRegistry);
         return mStatusBarKeyguardViewManager;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
index c7514a9..23eaed9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
@@ -17,6 +17,7 @@
 package com.android.systemui.keyguard;
 
 import static android.app.ActivityManager.TaskDescription;
+import static android.app.ActivityManager.StackId;
 
 import android.annotation.ColorInt;
 import android.annotation.UserIdInt;
@@ -31,6 +32,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.graphics.Color;
+import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -160,9 +162,23 @@
 
         credential.putExtra(Intent.EXTRA_INTENT, target.getIntentSender());
         try {
-            ActivityManager.getService().startConfirmDeviceCredentialIntent(credential);
+            ActivityManager.getService().startConfirmDeviceCredentialIntent(credential,
+                    getChallengeOptions().toBundle());
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to start confirm credential intent", e);
         }
     }
+
+    private ActivityOptions getChallengeOptions() {
+        // If we are taking up the whole screen, just use the default animation of clipping the
+        // credentials activity into the entire foreground.
+        if (!isInMultiWindowMode()) {
+            return ActivityOptions.makeBasic();
+        }
+
+        // Otherwise, animate the transition from this part of the screen to fullscreen
+        // using our own decor as the starting position.
+        final View view = getWindow().getDecorView();
+        return ActivityOptions.makeScaleUpAnimation(view, 0, 0, view.getWidth(), view.getHeight());
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
index 2c41a08..e6483f6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
@@ -42,9 +42,8 @@
         Intent intent = new Intent(KeyguardManager.ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER)
                 .setComponent(new ComponentName(mContext, WorkLockActivity.class))
                 .putExtra(Intent.EXTRA_USER_ID, userId)
-                .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
-                        | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
-                        | Intent.FLAG_ACTIVITY_SINGLE_TOP);
+                .addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
+                        | Intent.FLAG_ACTIVITY_CLEAR_TOP);
 
         final ActivityOptions options = ActivityOptions.makeBasic();
         options.setLaunchTaskId(taskId);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 12fda14..5727684 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -67,7 +67,7 @@
     private static final int MINIMIZE_STACK_MAX_DURATION = 200;
 
     // The fraction of the stack width that the user has to drag offscreen to minimize the PIP
-    private static final float MINIMIZE_OFFSCREEN_FRACTION = 0.15f;
+    private static final float MINIMIZE_OFFSCREEN_FRACTION = 0.2f;
 
     private final Context mContext;
     private final IActivityManager mActivityManager;
@@ -183,7 +183,7 @@
         mTouchState = new PipTouchState(mViewConfig);
         mFlingAnimationUtils = new FlingAnimationUtils(context, 2f);
         mGestures = new PipTouchGesture[] {
-                mDragToDismissGesture, mTapThroughGesture, mMinimizeGesture, mDefaultMovementGesture
+                mDragToDismissGesture, mDefaultMovementGesture
         };
         mMotionHelper = new PipMotionHelper(BackgroundThread.getHandler());
         registerInputConsumer();
@@ -231,6 +231,7 @@
 
     public void onMinimizedStateChanged(boolean isMinimized) {
         mIsMinimized = isMinimized;
+        mSnapAlgorithm.setMinimized(isMinimized);
     }
 
     public void onSnapToEdgeStateChanged(boolean isSnapToEdge) {
@@ -298,14 +299,13 @@
     }
 
     /**
-     * @return whether the current touch state is a horizontal drag offscreen.
+     * @return whether the current touch state places the pip partially offscreen.
      */
     private boolean isDraggingOffscreen(PipTouchState touchState) {
         PointF lastDelta = touchState.getLastTouchDelta();
         PointF downDelta = touchState.getDownTouchDelta();
         float left = mPinnedStackBounds.left + lastDelta.x;
-        return !(mBoundedPinnedStackBounds.left <= left && left <= mBoundedPinnedStackBounds.right)
-                && Math.abs(downDelta.x) > Math.abs(downDelta.y);
+        return !(mBoundedPinnedStackBounds.left <= left && left <= mBoundedPinnedStackBounds.right);
     }
 
     /**
@@ -429,7 +429,7 @@
                 mUpdatePinnedStackBoundsListener);
         mPinnedStackBoundsAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
-            public void onAnimationEnd(Animator animation) {
+            public void onAnimationStart(Animator animation) {
                 mMenuController.hideMenu();
             }
         });
@@ -590,115 +590,22 @@
     /**** Gestures ****/
 
     /**
-     * Gesture controlling dragging the PIP slightly offscreen to minimize it.
-     */
-    private PipTouchGesture mMinimizeGesture = new PipTouchGesture() {
-        @Override
-        boolean onMove(PipTouchState touchState) {
-            if (mEnableMinimizing) {
-                boolean isDraggingOffscreen = isDraggingOffscreen(touchState);
-                if (touchState.startedDragging() && isDraggingOffscreen) {
-                    // Reset the minimized state once we drag horizontally
-                    setMinimizedState(false);
-                }
-
-                if (touchState.allowDraggingOffscreen() && isDraggingOffscreen) {
-                    // Move the pinned stack, but ignore the vertical movement
-                    float left = mPinnedStackBounds.left + touchState.getLastTouchDelta().x;
-                    mTmpBounds.set(mPinnedStackBounds);
-                    mTmpBounds.offsetTo((int) left, mPinnedStackBounds.top);
-                    if (!mTmpBounds.equals(mPinnedStackBounds)) {
-                        mPinnedStackBounds.set(mTmpBounds);
-                        mMotionHelper.resizeToBounds(mPinnedStackBounds);
-                    }
-                    return true;
-                } else if (mIsMinimized && touchState.isDragging()) {
-                    // Move the pinned stack, but ignore the horizontal movement
-                    PointF lastDelta = touchState.getLastTouchDelta();
-                    float top = mPinnedStackBounds.top + lastDelta.y;
-                    top = Math.max(mBoundedPinnedStackBounds.top, Math.min(
-                            mBoundedPinnedStackBounds.bottom, top));
-                    mTmpBounds.set(mPinnedStackBounds);
-                    mTmpBounds.offsetTo(mPinnedStackBounds.left, (int) top);
-                    movePinnedStack(mTmpBounds);
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public boolean onUp(PipTouchState touchState) {
-            if (mEnableMinimizing) {
-                if (touchState.isDragging()) {
-                    if (isDraggingOffscreen(touchState)) {
-                        if (shouldMinimizedPinnedStack()) {
-                            setMinimizedState(true);
-                            animateToClosestMinimizedTarget();
-                            return true;
-                        }
-                    } else if (mIsMinimized) {
-                        PointF vel = touchState.getVelocity();
-                        if (vel.length() > mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
-                            flingToMinimizedSnapTarget(vel.y);
-                        } else {
-                            animateToClosestMinimizedTarget();
-                        }
-                        return true;
-                    }
-                } else if (mIsMinimized) {
-                    setMinimizedState(false);
-                    animateToClosestSnapTarget();
-                    return true;
-                }
-            }
-            return false;
-        }
-    };
-
-    /**
-     * Gesture controlling tapping on the PIP to show an overlay.
-     */
-    private PipTouchGesture mTapThroughGesture = new PipTouchGesture() {
-        @Override
-        boolean onMove(PipTouchState touchState) {
-            return false;
-        }
-
-        @Override
-        public boolean onUp(PipTouchState touchState) {
-            if (!touchState.isDragging() && !mIsMinimized && !mIsTappingThrough) {
-                mMenuController.showMenu();
-                mIsTappingThrough = true;
-                return true;
-            }
-            return false;
-        }
-    };
-
-    /**
      * Gesture controlling normal movement of the PIP.
      */
     private PipTouchGesture mDefaultMovementGesture = new PipTouchGesture() {
         @Override
         boolean onMove(PipTouchState touchState) {
-            if (touchState.startedDragging()) {
-                // For now, once the user has started a drag that the other gestures have not
-                // intercepted, disallow those gestures from intercepting again to drag offscreen
-                touchState.setDisallowDraggingOffscreen();
-            }
-
             if (touchState.isDragging()) {
                 // Move the pinned stack freely
                 PointF lastDelta = touchState.getLastTouchDelta();
                 float left = mPinnedStackBounds.left + lastDelta.x;
                 float top = mPinnedStackBounds.top + lastDelta.y;
-                if (!DEBUG_ALLOW_OUT_OF_BOUNDS_STACK) {
+                if (!touchState.allowDraggingOffscreen()) {
                     left = Math.max(mBoundedPinnedStackBounds.left, Math.min(
                             mBoundedPinnedStackBounds.right, left));
-                    top = Math.max(mBoundedPinnedStackBounds.top, Math.min(
-                            mBoundedPinnedStackBounds.bottom, top));
                 }
+                top = Math.max(mBoundedPinnedStackBounds.top, Math.min(
+                        mBoundedPinnedStackBounds.bottom, top));
                 mTmpBounds.set(mPinnedStackBounds);
                 mTmpBounds.offsetTo((int) left, (int) top);
                 movePinnedStack(mTmpBounds);
@@ -711,16 +618,58 @@
         public boolean onUp(PipTouchState touchState) {
             if (touchState.isDragging()) {
                 PointF vel = mTouchState.getVelocity();
-                float velocity = PointF.length(vel.x, vel.y);
+                if (!mIsMinimized && (shouldMinimizedPinnedStack()
+                        || isHorizontalFlingTowardsCurrentEdge(vel))) {
+                    // Pip should be minimized
+                    setMinimizedState(true);
+                    animateToClosestMinimizedTarget();
+                    return true;
+                }
+                if (mIsMinimized) {
+                    // If we're dragging and it wasn't a minimize gesture
+                    // then we shouldn't be minimized.
+                    setMinimizedState(false);
+                }
+
+                final float velocity = PointF.length(vel.x, vel.y);
                 if (velocity > mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
                     flingToSnapTarget(velocity, vel.x, vel.y);
                 } else {
                     animateToClosestSnapTarget();
                 }
+            } else if (mIsMinimized) {
+                // This was a tap, so no longer minimized
+                animateToClosestSnapTarget();
+                setMinimizedState(false);
+            } else if (!mIsTappingThrough) {
+                mMenuController.showMenu();
+                mIsTappingThrough = true;
             } else {
                 expandPinnedStackToFullscreen();
             }
             return true;
         }
     };
+
+    /**
+     * @return whether the gesture ending in the {@param vel} is fast enough to be a fling towards
+     *         the same edge the PIP is on. Used to identify a minimize gesture.
+     */
+    private boolean isHorizontalFlingTowardsCurrentEdge(PointF vel) {
+        final boolean isHorizontal = Math.abs(vel.x) > Math.abs(vel.y);
+        final boolean isFling = PointF.length(vel.x, vel.y) > mFlingAnimationUtils
+                .getMinVelocityPxPerSecond();
+        final boolean towardsCurrentEdge = onEdge(true /* left */) && vel.x < 0
+                || onEdge(false /* right */) && vel.x > 0;
+        return towardsCurrentEdge && isHorizontal && isFling;
+    }
+
+    private boolean onEdge(boolean checkLeft) {
+        if (checkLeft) {
+            return mPinnedStackBounds.left <= mBoundedPinnedStackBounds.left;
+        } else {
+            return mPinnedStackBounds.right >= mBoundedPinnedStackBounds.right
+                    + mPinnedStackBounds.width();
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 56947e5..964fefa 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -377,16 +377,18 @@
                 mCurrentPipBounds = mPipBounds;
                 break;
         }
-        try {
-            int animationDurationMs = -1;
-            if (wasRecentsShown
-                    && (mState == STATE_PIP_RECENTS || mState == STATE_PIP_RECENTS_FOCUSED)) {
-                animationDurationMs = mRecentsFocusChangedAnimationDurationMs;
+        if (mCurrentPipBounds != null) {
+            try {
+                int animationDurationMs = -1;
+                if (wasRecentsShown
+                        && (mState == STATE_PIP_RECENTS || mState == STATE_PIP_RECENTS_FOCUSED)) {
+                    animationDurationMs = mRecentsFocusChangedAnimationDurationMs;
+                }
+                mActivityManager.resizeStack(PINNED_STACK_ID, mCurrentPipBounds,
+                        true, true, true, animationDurationMs);
+            } catch (RemoteException e) {
+                Log.e(TAG, "resizeStack failed", e);
             }
-            mActivityManager.resizeStack(PINNED_STACK_ID, mCurrentPipBounds,
-                    true, true, true, animationDurationMs);
-        } catch (RemoteException e) {
-            Log.e(TAG, "resizeStack failed", e);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 2fe9e77..82ec69d 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -41,8 +41,9 @@
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.util.NotificationChannels;
 
 import java.io.PrintWriter;
 import java.text.NumberFormat;
@@ -97,7 +98,7 @@
     private SystemUIDialog mHighTempDialog;
 
     public PowerNotificationWarnings(Context context, NotificationManager notificationManager,
-            PhoneStatusBar phoneStatusBar) {
+            StatusBar statusBar) {
         mContext = context;
         mNoMan = notificationManager;
         mPowerMan = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
@@ -151,8 +152,7 @@
                 .setOngoing(true)
                 .setContentTitle(mContext.getString(R.string.invalid_charger_title))
                 .setContentText(mContext.getString(R.string.invalid_charger_text))
-                .setPriority(Notification.PRIORITY_MAX)
-                .setVisibility(Notification.VISIBILITY_PUBLIC)
+                .setChannel(NotificationChannels.ALERTS)
                 .setColor(mContext.getColor(
                         com.android.internal.R.color.system_notification_accent_color));
         SystemUI.overrideNotificationAppName(mContext, nb);
@@ -173,7 +173,7 @@
                 .setContentText(mContext.getString(textRes, percentage))
                 .setOnlyAlertOnce(true)
                 .setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_WARNING))
-                .setPriority(Notification.PRIORITY_MAX)
+                .setChannel(NotificationChannels.ALERTS)
                 .setVisibility(Notification.VISIBILITY_PUBLIC)
                 .setColor(mContext.getColor(
                         com.android.internal.R.color.battery_saver_mode_color));
@@ -241,7 +241,7 @@
                 .setShowWhen(false)
                 .setContentTitle(mContext.getString(R.string.high_temp_title))
                 .setContentText(mContext.getString(R.string.high_temp_notif_message))
-                .setPriority(Notification.PRIORITY_HIGH)
+                .setChannel(NotificationChannels.ALERTS)
                 .setVisibility(Notification.VISIBILITY_PUBLIC)
                 .setContentIntent(pendingBroadcast(ACTION_CLICKED_TEMP_WARNING))
                 .setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_TEMP_WARNING))
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index 1d4a5c7..3d36868 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -36,7 +36,7 @@
 import android.util.Slog;
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.StatusBar;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.Arrays;
@@ -72,7 +72,7 @@
         mWarnings = new PowerNotificationWarnings(
                 mContext,
                 (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE),
-                getComponent(PhoneStatusBar.class));
+                getComponent(StatusBar.class));
 
         ContentObserver obs = new ContentObserver(mHandler) {
             @Override
@@ -250,8 +250,8 @@
     }
 
     private void updateTemperatureWarning() {
-        PhoneStatusBar phoneStatusBar = getComponent(PhoneStatusBar.class);
-        if (phoneStatusBar != null && phoneStatusBar.isDeviceInVrMode()) {
+        StatusBar statusBar = getComponent(StatusBar.class);
+        if (statusBar != null && statusBar.isDeviceInVrMode()) {
             // ensure the warning isn't showing, since VR shows its own warning
             mWarnings.dismissTemperatureWarning();
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 409943d..602f9bf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -193,9 +193,9 @@
                 translationXBuilder.addFloat(label, "translationX", -xDiff, 0);
                 translationYBuilder.addFloat(label, "translationY", -yDiff, 0);
 
-                mTopFiveQs.add(tileIcon);
+                mTopFiveQs.add(tileView.getIcon());
                 mTopFiveQs.add(tileView.getBgCicle());
-                mAllViews.add(tileIcon);
+                mAllViews.add(tileView.getIcon());
                 mAllViews.add(quickTileView);
             } else if (mFullRows && isIconInAnimatedRow(count)) {
                 // TODO: Refactor some of this, it shares a lot with the above block.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index 5c23eb7..ce72942 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -307,8 +307,10 @@
     }
 
     public void destroy() {
-        mServices.values().forEach(service -> service.handleDestroy());
-        mContext.unregisterReceiver(mRequestListeningReceiver);
+        synchronized (mServices) {
+            mServices.values().forEach(service -> service.handleDestroy());
+            mContext.unregisterReceiver(mRequestListeningReceiver);
+        }
     }
 
     private final BroadcastReceiver mRequestListeningReceiver = new BroadcastReceiver() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
index 7e04b67..06f4d9d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.graphics.drawable.Drawable;
 import android.service.quicksettings.Tile;
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
@@ -42,8 +41,6 @@
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QS.DetailAdapter;
 import com.android.systemui.qs.QSTile;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
-import com.android.systemui.qs.external.TileColorPicker;
 import com.android.systemui.statusbar.policy.BatteryController;
 
 import java.text.NumberFormat;
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 75c4a75..bdc95c0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -38,7 +38,7 @@
 import com.android.systemui.qs.SignalTileView;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
-import com.android.systemui.statusbar.policy.SignalCallbackAdapter;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 
 /** Quick settings tile: Cellular **/
 public class CellularTile extends QSTile<QSTile.SignalState> {
@@ -197,9 +197,10 @@
         String enabledDesc;
         boolean noSim;
         boolean isDataTypeIconWide;
+        boolean roaming;
     }
 
-    private final class CellSignalCallback extends SignalCallbackAdapter {
+    private final class CellSignalCallback implements SignalCallback {
         private final CallbackInfo mInfo = new CallbackInfo();
         @Override
         public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
@@ -211,7 +212,7 @@
         @Override
         public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
                 int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
-                String description, boolean isWide, int subId) {
+                String description, boolean isWide, int subId, boolean roaming) {
             if (qsIcon == null) {
                 // Not data sim, don't display.
                 return;
@@ -225,6 +226,7 @@
             mInfo.activityOut = activityOut;
             mInfo.enabledDesc = description;
             mInfo.isDataTypeIconWide = qsType != 0 && isWide;
+            mInfo.roaming = roaming;
             refreshState(mInfo);
         }
 
@@ -294,6 +296,8 @@
             final DataUsageController.DataUsageInfo info = mDataController.getDataUsageInfo();
             if (info == null) return v;
             v.bind(info);
+            v.findViewById(R.id.roaming_text).setVisibility(mSignalCallback.mInfo.roaming
+                    ? View.VISIBLE : View.INVISIBLE);
             return v;
         }
 
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 54b41ac..2d61857 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -43,7 +43,7 @@
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
-import com.android.systemui.statusbar.policy.SignalCallbackAdapter;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 
 import java.util.List;
 
@@ -256,7 +256,7 @@
         }
     }
 
-    protected final class WifiSignalCallback extends SignalCallbackAdapter {
+    protected final class WifiSignalCallback implements SignalCallback {
         final CallbackInfo mInfo = new CallbackInfo();
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 06fadd1..a6fe0ea 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -88,7 +88,7 @@
 import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.recents.views.RecentsView;
 import com.android.systemui.recents.views.SystemBarScrimViews;
-import com.android.systemui.statusbar.BaseStatusBar;
+import com.android.systemui.statusbar.phone.StatusBar;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -283,7 +283,7 @@
         dismissEvent.addPostAnimationCallback(new LaunchHomeRunnable(mHomeIntent,
                 overrideAnimation));
         Recents.getSystemServices().sendCloseSystemWindows(
-                BaseStatusBar.SYSTEM_DIALOG_REASON_HOME_KEY);
+                StatusBar.SYSTEM_DIALOG_REASON_HOME_KEY);
         EventBus.getDefault().send(dismissEvent);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index cf6357b..9a8b267 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -18,7 +18,6 @@
 
 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
 import static android.app.ActivityManager.StackId.isHomeOrRecentsStack;
 import static android.view.View.MeasureSpec;
 
@@ -77,9 +76,8 @@
 import com.android.systemui.recents.views.TaskViewHeader;
 import com.android.systemui.recents.views.TaskViewTransform;
 import com.android.systemui.stackdivider.DividerView;
-import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.phone.NavigationBarGestureHelper;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.StatusBar;
 
 import java.util.ArrayList;
 
@@ -229,7 +227,7 @@
      */
     public void onStartScreenPinning(Context context, int taskId) {
         SystemUIApplication app = (SystemUIApplication) context;
-        PhoneStatusBar statusBar = app.getComponent(PhoneStatusBar.class);
+        StatusBar statusBar = app.getComponent(StatusBar.class);
         if (statusBar != null) {
             statusBar.showScreenPinningRequest(taskId, false);
         }
@@ -351,7 +349,7 @@
                         growTarget);
 
                 // Only close the other system windows if we are actually showing recents
-                ssp.sendCloseSystemWindows(BaseStatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS);
+                ssp.sendCloseSystemWindows(StatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS);
                 mLastToggleTime = SystemClock.elapsedRealtime();
             }
         } catch (ActivityNotFoundException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
index a2a8199..a691a424 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
@@ -30,6 +30,8 @@
 import android.widget.FrameLayout.LayoutParams;
 
 import com.android.systemui.R;
+import com.android.systemui.pip.tv.PipManager;
+import com.android.systemui.pip.tv.PipRecentsOverlayManager;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsActivityLaunchState;
 import com.android.systemui.recents.RecentsConfiguration;
@@ -57,9 +59,7 @@
 import com.android.systemui.recents.tv.views.TaskCardView;
 import com.android.systemui.recents.tv.views.TaskStackHorizontalGridView;
 import com.android.systemui.recents.tv.views.TaskStackHorizontalViewAdapter;
-import com.android.systemui.statusbar.BaseStatusBar;
-import com.android.systemui.pip.tv.PipManager;
-import com.android.systemui.pip.tv.PipRecentsOverlayManager;
+import com.android.systemui.statusbar.phone.StatusBar;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -258,7 +258,7 @@
             @Override
             public void run() {
                 Recents.getSystemServices().sendCloseSystemWindows(
-                        BaseStatusBar.SYSTEM_DIALOG_REASON_HOME_KEY);
+                        StatusBar.SYSTEM_DIALOG_REASON_HOME_KEY);
             }
         };
         DismissRecentsToHomeAnimationStarted dismissEvent =
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index 2bd651b..6a66fca7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -51,7 +51,7 @@
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
-import com.android.systemui.statusbar.BaseStatusBar;
+import com.android.systemui.statusbar.phone.StatusBar;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -170,7 +170,7 @@
             }
         }
         Recents.getSystemServices().sendCloseSystemWindows(
-                BaseStatusBar.SYSTEM_DIALOG_REASON_HOME_KEY);
+                StatusBar.SYSTEM_DIALOG_REASON_HOME_KEY);
     }
 
     public IRemoteCallback wrapStartedListener(final OnAnimationStartedListener listener) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index e941c3b..45e766c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -258,11 +258,6 @@
     }
 
     @Override
-    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
-        // Prevent any children from being focusable during talkback
-    }
-
-    @Override
     public boolean hasOverlappingRendering() {
         return false;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java
index 759daf1..2c3e78f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java
@@ -18,7 +18,6 @@
 
 import android.app.ActivityManager;
 import android.content.Context;
-import android.content.res.Configuration;
 import android.graphics.Point;
 import android.os.Bundle;
 import android.util.SparseArray;
@@ -29,6 +28,7 @@
 import com.android.systemui.R;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.ui.ShowApplicationInfoEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
 import com.android.systemui.recents.misc.Utilities;
@@ -39,8 +39,6 @@
 
     private final TaskView mTaskView;
 
-    protected static final int OPEN = R.id.action_open;
-    protected static final int DIMISS = R.id.action_dimiss;
     protected static final int SPLIT_TASK_TOP = R.id.action_split_task_to_top;
     protected static final int SPLIT_TASK_LEFT = R.id.action_split_task_to_left;
     protected static final int SPLIT_TASK_RIGHT = R.id.action_split_task_to_right;
@@ -50,10 +48,6 @@
     public TaskViewAccessibilityDelegate(TaskView taskView) {
         mTaskView = taskView;
         Context context = taskView.getContext();
-        mActions.put(OPEN, new AccessibilityAction(OPEN,
-                context.getString(R.string.recents_accessibility_open)));
-        mActions.put(DIMISS, new AccessibilityAction(DIMISS,
-                context.getString(R.string.recents_accessibility_dismissed)));
         mActions.put(SPLIT_TASK_TOP, new AccessibilityAction(SPLIT_TASK_TOP,
                 context.getString(R.string.recents_accessibility_split_screen_top)));
         mActions.put(SPLIT_TASK_LEFT, new AccessibilityAction(SPLIT_TASK_LEFT,
@@ -65,8 +59,6 @@
     @Override
     public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(host, info);
-        info.addAction(mActions.get(OPEN));
-        info.addAction(mActions.get(DIMISS));
         if (ActivityManager.supportsSplitScreenMultiWindow()
                 && !Recents.getSystemServices().hasDockedTask()) {
             TaskStack.DockState[] dockStates = Recents.getConfiguration()
@@ -85,11 +77,7 @@
 
     @Override
     public boolean performAccessibilityAction(View host, int action, Bundle args) {
-        if (action == OPEN) {
-            mTaskView.onClick(host);
-        } else if (action == DIMISS) {
-            mTaskView.dismissTask();
-        } else if (action == SPLIT_TASK_TOP) {
+        if (action == SPLIT_TASK_TOP) {
             simulateDragIntoMultiwindow(TaskStack.DockState.TOP);
         } else if (action == SPLIT_TASK_LEFT) {
             simulateDragIntoMultiwindow(TaskStack.DockState.LEFT);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index b318ea7..0777163 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -462,6 +462,7 @@
                 mTaskBarViewLightTextColor : mTaskBarViewDarkTextColor);
         mDismissButton.setImageDrawable(t.useLightOnPrimaryColor ?
                 mLightDismissDrawable : mDarkDismissDrawable);
+        mDismissButton.setContentDescription(t.dismissDescription);
         mDismissButton.setOnClickListener(this);
         mDismissButton.setClickable(false);
         ((RippleDrawable) mDismissButton.getBackground()).setForceSoftware(true);
@@ -498,6 +499,7 @@
 
         // In accessibility, a single click on the focused app info button will show it
         if (touchExplorationEnabled) {
+            mIconView.setContentDescription(t.appInfoDescription);
             mIconView.setOnClickListener(this);
             mIconView.setClickable(true);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index db021ff..7135caf 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -62,6 +62,7 @@
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
+import com.android.systemui.util.NotificationChannels;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -178,6 +179,7 @@
 
         // The public notification will show similar info but with the actual screenshot omitted
         mPublicNotificationBuilder = new Notification.Builder(context)
+                .setChannel(NotificationChannels.SCREENSHOTS)
                 .setContentTitle(r.getString(R.string.screenshot_saving_title))
                 .setContentText(r.getString(R.string.screenshot_saving_text))
                 .setSmallIcon(R.drawable.stat_notify_image)
@@ -189,6 +191,7 @@
         SystemUI.overrideNotificationAppName(context, mPublicNotificationBuilder);
 
         mNotificationBuilder = new Notification.Builder(context)
+            .setChannel(NotificationChannels.SCREENSHOTS)
             .setTicker(r.getString(R.string.screenshot_saving_ticker)
                     + (mTickerAddSpace ? " " : ""))
             .setContentTitle(r.getString(R.string.screenshot_saving_title))
@@ -332,6 +335,7 @@
 
             // Update the text and the icon for the existing notification
             mPublicNotificationBuilder
+                    .setChannel(NotificationChannels.SCREENSHOTS)
                     .setContentTitle(r.getString(R.string.screenshot_saved_title))
                     .setContentText(r.getString(R.string.screenshot_saved_text))
                     .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
@@ -340,6 +344,7 @@
                     .setColor(context.getColor(
                             com.android.internal.R.color.system_notification_accent_color));
             mNotificationBuilder
+                .setChannel(NotificationChannels.SCREENSHOTS)
                 .setContentTitle(r.getString(R.string.screenshot_saved_title))
                 .setContentText(r.getString(R.string.screenshot_saved_text))
                 .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index 3cd2a7a..b9a0f74 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -44,6 +44,7 @@
     private boolean mVisible = false;
     private boolean mMinimized = false;
     private boolean mAdjustedForIme = false;
+    private boolean mHomeStackResizable = false;
     private ForcedResizableInfoActivityController mForcedResizableController;
 
     @Override
@@ -75,6 +76,7 @@
         mView = (DividerView)
                 LayoutInflater.from(mContext).inflate(R.layout.docked_stack_divider, null);
         mView.setVisibility(mVisible ? View.VISIBLE : View.INVISIBLE);
+        mView.setMinimizedDockStack(mMinimized, mHomeStackResizable);
         final int size = mContext.getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.docked_stack_divider_thickness);
         final boolean landscape = configuration.orientation == ORIENTATION_LANDSCAPE;
@@ -92,7 +94,7 @@
         removeDivider();
         addDivider(configuration);
         if (mMinimized) {
-            mView.setMinimizedDockStack(true);
+            mView.setMinimizedDockStack(true, mHomeStackResizable);
             updateTouchable();
         }
     }
@@ -106,13 +108,14 @@
                     mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
 
                     // Update state because animations won't finish.
-                    mView.setMinimizedDockStack(mMinimized);
+                    mView.setMinimizedDockStack(mMinimized, mHomeStackResizable);
                 }
             }
         });
     }
 
-    private void updateMinimizedDockedStack(final boolean minimized, final long animDuration) {
+    private void updateMinimizedDockedStack(final boolean minimized, final long animDuration,
+            final boolean isHomeStackResizable) {
         mView.post(new Runnable() {
             @Override
             public void run() {
@@ -120,9 +123,9 @@
                     mMinimized = minimized;
                     updateTouchable();
                     if (animDuration > 0) {
-                        mView.setMinimizedDockStack(minimized, animDuration);
+                        mView.setMinimizedDockStack(minimized, animDuration, isHomeStackResizable);
                     } else {
-                        mView.setMinimizedDockStack(minimized);
+                        mView.setMinimizedDockStack(minimized, isHomeStackResizable);
                     }
                 }
             }
@@ -139,7 +142,7 @@
     }
 
     private void updateTouchable() {
-        mWindowManager.setTouchable(!mMinimized && !mAdjustedForIme);
+        mWindowManager.setTouchable((mHomeStackResizable || !mMinimized) && !mAdjustedForIme);
     }
 
     @Override
@@ -162,9 +165,10 @@
         }
 
         @Override
-        public void onDockedStackMinimizedChanged(boolean minimized, long animDuration)
-                throws RemoteException {
-            updateMinimizedDockedStack(minimized, animDuration);
+        public void onDockedStackMinimizedChanged(boolean minimized, long animDuration,
+                boolean isHomeStackResizable) throws RemoteException {
+            mHomeStackResizable = isHomeStackResizable;
+            updateMinimizedDockedStack(minimized, animDuration, isHomeStackResizable);
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 47d2def..49035ba 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -64,6 +64,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;
@@ -123,6 +124,8 @@
     private boolean mMoving;
     private int mTouchSlop;
     private boolean mBackgroundLifted;
+    private boolean mIsInMinimizeInteraction;
+    private int mDividerPositionBeforeMinimized;
 
     private int mDividerInsets;
     private int mDisplayWidth;
@@ -145,6 +148,7 @@
     private VelocityTracker mVelocityTracker;
     private FlingAnimationUtils mFlingAnimationUtils;
     private DividerSnapAlgorithm mSnapAlgorithm;
+    private DividerSnapAlgorithm mMinimizedSnapAlgorithm;
     private final Rect mStableInsets = new Rect();
 
     private boolean mGrowRecents;
@@ -154,6 +158,7 @@
     private int mExitStartPosition;
     private GestureDetector mGestureDetector;
     private boolean mDockedStackMinimized;
+    private boolean mHomeStackResizable;
     private boolean mAdjustedForIme;
     private DividerState mState;
 
@@ -350,8 +355,9 @@
                 || mStableInsets.bottom != insets.getStableInsetBottom()) {
             mStableInsets.set(insets.getStableInsetLeft(), insets.getStableInsetTop(),
                     insets.getStableInsetRight(), insets.getStableInsetBottom());
-            if (mSnapAlgorithm != null) {
+            if (mSnapAlgorithm != null || mMinimizedSnapAlgorithm != null) {
                 mSnapAlgorithm = null;
+                mMinimizedSnapAlgorithm = null;
                 initializeSnapAlgorithm();
             }
         }
@@ -446,11 +452,17 @@
             mSnapAlgorithm = new DividerSnapAlgorithm(getContext().getResources(), mDisplayWidth,
                     mDisplayHeight, mDividerSize, isHorizontalDivision(), mStableInsets);
         }
+        if (mMinimizedSnapAlgorithm == null) {
+            mMinimizedSnapAlgorithm = new DividerSnapAlgorithm(getContext().getResources(),
+                    mDisplayWidth, mDisplayHeight, mDividerSize, isHorizontalDivision(),
+                    mStableInsets, mDockedStackMinimized && mHomeStackResizable);
+        }
     }
 
     public DividerSnapAlgorithm getSnapAlgorithm() {
         initializeSnapAlgorithm();
-        return mSnapAlgorithm;
+        return mDockedStackMinimized && mHomeStackResizable ? mMinimizedSnapAlgorithm :
+                mSnapAlgorithm;
     }
 
     public int getCurrentPosition() {
@@ -495,7 +507,7 @@
                     mMoving = true;
                 }
                 if (mMoving && mDockSide != WindowManager.DOCKED_INVALID) {
-                    SnapTarget snapTarget = mSnapAlgorithm.calculateSnapTarget(
+                    SnapTarget snapTarget = getSnapAlgorithm().calculateSnapTarget(
                             mStartPosition, 0 /* velocity */, false /* hardDismiss */);
                     resizeStackDelayed(calculatePosition(x, y), mStartPosition, snapTarget);
                 }
@@ -551,9 +563,10 @@
 
     private void fling(int position, float velocity, boolean avoidDismissStart,
             boolean logMetrics) {
-        SnapTarget snapTarget = mSnapAlgorithm.calculateSnapTarget(position, velocity);
-        if (avoidDismissStart && snapTarget == mSnapAlgorithm.getDismissStartTarget()) {
-            snapTarget = mSnapAlgorithm.getFirstSplitTarget();
+        DividerSnapAlgorithm currentSnapAlgorithm = getSnapAlgorithm();
+        SnapTarget snapTarget = currentSnapAlgorithm.calculateSnapTarget(position, velocity);
+        if (avoidDismissStart && snapTarget == currentSnapAlgorithm.getDismissStartTarget()) {
+            snapTarget = currentSnapAlgorithm.getFirstSplitTarget();
         }
         if (logMetrics) {
             logResizeEvent(snapTarget);
@@ -574,6 +587,10 @@
 
     private ValueAnimator getFlingAnimator(int position, final SnapTarget snapTarget,
             final long endDelay) {
+        if (mCurrentAnimator != null) {
+            cancelFlingAnimation();
+            updateDockSide();
+        }
         final boolean taskPositionSameAtEnd = snapTarget.flag == SnapTarget.FLAG_NONE;
         ValueAnimator anim = ValueAnimator.ofInt(position, snapTarget.position);
         anim.addUpdateListener(animation -> resizeStackDelayed((int) animation.getAnimatedValue(),
@@ -590,6 +607,12 @@
             mExitAnimationRunning = false;
             EventBus.getDefault().send(new StoppedDragingEvent());
         };
+        Runnable notCancelledEndAction = () -> {
+            // Reset minimized divider position after unminimized state animation finishes
+            if (!mDockedStackMinimized && mIsInMinimizeInteraction) {
+                mIsInMinimizeInteraction = false;
+            }
+        };
         anim.addListener(new AnimatorListenerAdapter() {
 
             private boolean mCancelled;
@@ -612,8 +635,14 @@
                 }
                 if (delay == 0) {
                     endAction.run();
+                    if (!mCancelled) {
+                        notCancelledEndAction.run();
+                    }
                 } else {
                     mHandler.postDelayed(endAction, delay);
+                    if (!mCancelled) {
+                        mHandler.postDelayed(notCancelledEndAction, delay);
+                    }
                 }
             }
         });
@@ -692,57 +721,92 @@
     }
 
 
-    public void setMinimizedDockStack(boolean minimized) {
+    public void setMinimizedDockStack(boolean minimized, boolean isHomeStackResizable) {
+        mHomeStackResizable = isHomeStackResizable;
         updateDockSide();
-        mHandle.setAlpha(minimized ? 0f : 1f);
         if (!minimized) {
             resetBackground();
-        } else if (mDockSide == WindowManager.DOCKED_TOP) {
-            mBackground.setPivotY(0);
-            mBackground.setScaleY(MINIMIZE_DOCK_SCALE);
-        } else if (mDockSide == WindowManager.DOCKED_LEFT
-                || mDockSide == WindowManager.DOCKED_RIGHT) {
-            mBackground.setPivotX(mDockSide == WindowManager.DOCKED_LEFT
-                    ? 0
-                    : mBackground.getWidth());
-            mBackground.setScaleX(MINIMIZE_DOCK_SCALE);
+        } else if (!isHomeStackResizable) {
+            if (mDockSide == WindowManager.DOCKED_TOP) {
+                mBackground.setPivotY(0);
+                mBackground.setScaleY(MINIMIZE_DOCK_SCALE);
+            } else if (mDockSide == WindowManager.DOCKED_LEFT
+                    || mDockSide == WindowManager.DOCKED_RIGHT) {
+                mBackground.setPivotX(mDockSide == WindowManager.DOCKED_LEFT
+                        ? 0
+                        : mBackground.getWidth());
+                mBackground.setScaleX(MINIMIZE_DOCK_SCALE);
+            }
         }
         mMinimizedShadow.setAlpha(minimized ? 1f : 0f);
-        mDockedStackMinimized = minimized;
+        if (!isHomeStackResizable) {
+            mHandle.setAlpha(minimized ? 0f : 1f);
+            mDockedStackMinimized = minimized;
+        } else if (mDockedStackMinimized != minimized) {
+            if (mStableInsets.isEmpty()) {
+                SystemServicesProxy.getInstance(mContext).getStableInsets(mStableInsets);
+            }
+            if (!mIsInMinimizeInteraction && minimized) {
+                mIsInMinimizeInteraction = true;
+                mDividerPositionBeforeMinimized = DockedDividerUtils.calculateMiddlePosition(
+                        isHorizontalDivision(), mStableInsets, mDisplayWidth, mDisplayHeight,
+                        mDividerSize);
+            }
+            mMinimizedSnapAlgorithm = null;
+            mDockedStackMinimized = minimized;
+            initializeSnapAlgorithm();
+        }
     }
 
-    public void setMinimizedDockStack(boolean minimized, long animDuration) {
+    public void setMinimizedDockStack(boolean minimized, long animDuration,
+            boolean isHomeStackResizable) {
+        mHomeStackResizable = isHomeStackResizable;
         updateDockSide();
-        mHandle.animate()
-                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
-                .setDuration(animDuration)
-                .alpha(minimized ? 0f : 1f)
-                .start();
-        if (mDockSide == WindowManager.DOCKED_TOP) {
-            mBackground.setPivotY(0);
-            mBackground.animate()
-                    .scaleY(minimized ? MINIMIZE_DOCK_SCALE : 1f);
-        } else if (mDockSide == WindowManager.DOCKED_LEFT
-                || mDockSide == WindowManager.DOCKED_RIGHT) {
-            mBackground.setPivotX(mDockSide == WindowManager.DOCKED_LEFT
-                    ? 0
-                    : mBackground.getWidth());
-            mBackground.animate()
-                    .scaleX(minimized ? MINIMIZE_DOCK_SCALE : 1f);
+        if (!isHomeStackResizable) {
+            mMinimizedShadow.animate()
+                    .alpha(minimized ? 1f : 0f)
+                    .setInterpolator(Interpolators.ALPHA_IN)
+                    .setDuration(animDuration)
+                    .start();
+            mHandle.animate()
+                    .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+                    .setDuration(animDuration)
+                    .alpha(minimized ? 0f : 1f)
+                    .start();
+            if (mDockSide == WindowManager.DOCKED_TOP) {
+                mBackground.setPivotY(0);
+                mBackground.animate()
+                        .scaleY(minimized ? MINIMIZE_DOCK_SCALE : 1f);
+            } else if (mDockSide == WindowManager.DOCKED_LEFT
+                    || mDockSide == WindowManager.DOCKED_RIGHT) {
+                mBackground.setPivotX(mDockSide == WindowManager.DOCKED_LEFT
+                        ? 0
+                        : mBackground.getWidth());
+                mBackground.animate()
+                        .scaleX(minimized ? MINIMIZE_DOCK_SCALE : 1f);
+            }
+            mDockedStackMinimized = minimized;
+        } else if (mDockedStackMinimized != minimized) {
+            mIsInMinimizeInteraction = true;
+            if (minimized) {
+                mDividerPositionBeforeMinimized = getCurrentPosition();
+            }
+            mMinimizedSnapAlgorithm = null;
+            mDockedStackMinimized = minimized;
+            initializeSnapAlgorithm();
+            stopDragging(getCurrentPosition(), minimized ?
+                            mMinimizedSnapAlgorithm.getMiddleTarget() :
+                            mSnapAlgorithm.calculateNonDismissingSnapTarget(
+                                    mDividerPositionBeforeMinimized),
+                    animDuration, Interpolators.FAST_OUT_SLOW_IN, 0);
         }
         if (!minimized) {
             mBackground.animate().withEndAction(mResetBackgroundRunnable);
         }
-        mMinimizedShadow.animate()
-                .alpha(minimized ? 1f : 0f)
-                .setInterpolator(Interpolators.ALPHA_IN)
-                .setDuration(animDuration)
-                .start();
         mBackground.animate()
                 .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
                 .setDuration(animDuration)
                 .start();
-        mDockedStackMinimized = minimized;
     }
 
     public void setAdjustedForIme(boolean adjustedForIme) {
@@ -809,6 +873,7 @@
         mDisplayWidth = info.logicalWidth;
         mDisplayHeight = info.logicalHeight;
         mSnapAlgorithm = null;
+        mMinimizedSnapAlgorithm = null;
         initializeSnapAlgorithm();
     }
 
@@ -871,6 +936,15 @@
         }
 
         mLastResizeRect.set(mDockedRect);
+        if (mHomeStackResizable && mIsInMinimizeInteraction) {
+            calculateBoundsForPosition(mDividerPositionBeforeMinimized, mDockSide, mDockedTaskRect);
+            calculateBoundsForPosition(mDividerPositionBeforeMinimized,
+                    DockedDividerUtils.invertDockSide(mDockSide), mOtherTaskRect);
+            mWindowManagerProxy.resizeDockedStack(mDockedRect, mDockedTaskRect, mDockedTaskRect,
+                    mOtherTaskRect, null);
+            return;
+        }
+
         if (mEntranceAnimationRunning && taskPosition != TASK_POSITION_SAME) {
             if (mCurrentAnimator != null) {
                 calculateBoundsForPosition(taskPosition, mDockSide, mDockedTaskRect);
@@ -922,7 +996,7 @@
         } else {
             mWindowManagerProxy.resizeDockedStack(mDockedRect, null, null, null, null);
         }
-        SnapTarget closestDismissTarget = mSnapAlgorithm.getClosestDismissTarget(position);
+        SnapTarget closestDismissTarget = getSnapAlgorithm().getClosestDismissTarget(position);
         float dimFraction = getDimFraction(position, closestDismissTarget);
         mWindowManagerProxy.setResizeDimLayer(dimFraction != 0f,
                 getStackIdForDismissTarget(closestDismissTarget),
@@ -943,7 +1017,7 @@
         if (mEntranceAnimationRunning) {
             return 0f;
         }
-        float fraction = mSnapAlgorithm.calculateDismissingFraction(position);
+        float fraction = getSnapAlgorithm().calculateDismissingFraction(position);
         fraction = Math.max(0, Math.min(fraction, 1f));
         fraction = DIM_INTERPOLATOR.getInterpolation(fraction);
         if (hasInsetsAtDismissTarget(dismissTarget)) {
@@ -959,13 +1033,13 @@
      */
     private boolean hasInsetsAtDismissTarget(SnapTarget dismissTarget) {
         if (isHorizontalDivision()) {
-            if (dismissTarget == mSnapAlgorithm.getDismissStartTarget()) {
+            if (dismissTarget == getSnapAlgorithm().getDismissStartTarget()) {
                 return mStableInsets.top != 0;
             } else {
                 return mStableInsets.bottom != 0;
             }
         } else {
-            if (dismissTarget == mSnapAlgorithm.getDismissStartTarget()) {
+            if (dismissTarget == getSnapAlgorithm().getDismissStartTarget()) {
                 return mStableInsets.left != 0;
             } else {
                 return mStableInsets.right != 0;
@@ -1135,6 +1209,7 @@
         if (mStableInsets.isEmpty()) {
             SystemServicesProxy.getInstance(mContext).getStableInsets(mStableInsets);
             mSnapAlgorithm = null;
+            mMinimizedSnapAlgorithm = null;
             initializeSnapAlgorithm();
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
deleted file mode 100644
index 926f610..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ /dev/null
@@ -1,2555 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.app.ActivityManager;
-import android.app.ActivityManager.StackId;
-import android.app.ActivityOptions;
-import android.app.INotificationManager;
-import android.app.KeyguardManager;
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.app.RemoteInput;
-import android.app.TaskStackBuilder;
-import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.IntentSender;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.UserInfo;
-import android.content.res.Configuration;
-import android.database.ContentObserver;
-import android.graphics.PointF;
-import android.graphics.Rect;
-import android.os.AsyncTask;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.service.dreams.DreamService;
-import android.service.dreams.IDreamManager;
-import android.service.notification.NotificationListenerService;
-import android.service.notification.NotificationListenerService.RankingMap;
-import android.service.notification.StatusBarNotification;
-import android.service.vr.IVrManager;
-import android.service.vr.IVrStateCallbacks;
-import android.text.TextUtils;
-import android.util.ArraySet;
-import android.util.Log;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.util.SparseBooleanArray;
-import android.view.Display;
-import android.view.IWindowManager;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewAnimationUtils;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
-import android.view.accessibility.AccessibilityManager;
-import android.widget.RemoteViews;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.statusbar.StatusBarIcon;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardHostView.OnDismissAction;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.DejankUtils;
-import com.android.systemui.Dependency;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.RecentsComponent;
-import com.android.systemui.SwipeHelper;
-import com.android.systemui.SystemUI;
-import com.android.systemui.assist.AssistManager;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.statusbar.NotificationData.Entry;
-import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.statusbar.policy.PreviewInflater;
-import com.android.systemui.statusbar.policy.RemoteInputView;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.stack.StackStateAnimator;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Set;
-import java.util.Stack;
-
-public abstract class BaseStatusBar extends SystemUI implements
-        CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
-        ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment,
-        ExpandableNotificationRow.OnExpandClickListener {
-    public static final String TAG = "StatusBar";
-    public static final boolean DEBUG = false;
-    public static final boolean MULTIUSER_DEBUG = false;
-
-    public static final boolean ENABLE_REMOTE_INPUT =
-            SystemProperties.getBoolean("debug.enable_remote_input", true);
-    public static final boolean ENABLE_CHILD_NOTIFICATIONS
-            = SystemProperties.getBoolean("debug.child_notifs", true);
-    public static final boolean FORCE_REMOTE_INPUT_HISTORY =
-            SystemProperties.getBoolean("debug.force_remoteinput_history", false);
-    private static boolean ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT = false;
-
-    protected static final int MSG_SHOW_RECENT_APPS = 1019;
-    protected static final int MSG_HIDE_RECENT_APPS = 1020;
-    protected static final int MSG_TOGGLE_RECENTS_APPS = 1021;
-    protected static final int MSG_PRELOAD_RECENT_APPS = 1022;
-    protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023;
-    protected static final int MSG_SHOW_NEXT_AFFILIATED_TASK = 1024;
-    protected static final int MSG_SHOW_PREV_AFFILIATED_TASK = 1025;
-    protected static final int MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU = 1026;
-    protected static final int MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU = 1027;
-
-    protected static final boolean ENABLE_HEADS_UP = true;
-    protected static final String SETTING_HEADS_UP_TICKER = "ticker_gets_heads_up";
-
-    private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
-
-    // Should match the values in PhoneWindowManager
-    public static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
-    public static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
-
-    private static final String BANNER_ACTION_CANCEL =
-            "com.android.systemui.statusbar.banner_action_cancel";
-    private static final String BANNER_ACTION_SETUP =
-            "com.android.systemui.statusbar.banner_action_setup";
-    private static final String NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION
-            = "com.android.systemui.statusbar.work_challenge_unlocked_notification_action";
-
-    protected CommandQueue mCommandQueue;
-    protected IStatusBarService mBarService;
-    protected H mHandler = createHandler();
-
-    // all notifications
-    protected NotificationData mNotificationData;
-    protected NotificationStackScrollLayout mStackScroller;
-
-    protected NotificationGroupManager mGroupManager = new NotificationGroupManager();
-
-    protected RemoteInputController mRemoteInputController;
-
-    // for heads up notifications
-    protected HeadsUpManager mHeadsUpManager;
-
-    // handling reordering
-    protected VisualStabilityManager mVisualStabilityManager = new VisualStabilityManager();
-
-    protected int mCurrentUserId = 0;
-    final protected SparseArray<UserInfo> mCurrentProfiles = new SparseArray<UserInfo>();
-
-    protected int mLayoutDirection = -1; // invalid
-    protected AccessibilityManager mAccessibilityManager;
-
-    protected boolean mDeviceInteractive;
-
-    protected boolean mVisible;
-    protected ArraySet<Entry> mHeadsUpEntriesToRemoveOnSwitch = new ArraySet<>();
-    protected ArraySet<Entry> mRemoteInputEntriesToRemoveOnCollapse = new ArraySet<>();
-
-    /**
-     * Notifications with keys in this set are not actually around anymore. We kept them around
-     * when they were canceled in response to a remote input interaction. This allows us to show
-     * what you replied and allows you to continue typing into it.
-     */
-    protected ArraySet<String> mKeysKeptForRemoteInput = new ArraySet<>();
-
-    // mScreenOnFromKeyguard && mVisible.
-    private boolean mVisibleToUser;
-
-    private Locale mLocale;
-    private float mFontScale;
-
-    protected boolean mUseHeadsUp = false;
-    protected boolean mHeadsUpTicker = false;
-    protected boolean mDisableNotificationAlerts = false;
-
-    protected DevicePolicyManager mDevicePolicyManager;
-    protected IDreamManager mDreamManager;
-    protected PowerManager mPowerManager;
-    protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
-
-    // public mode, private notifications, etc
-    private final SparseBooleanArray mLockscreenPublicMode = new SparseBooleanArray();
-    private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
-    private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray();
-
-    private UserManager mUserManager;
-    private int mDensity;
-
-    protected KeyguardManager mKeyguardManager;
-    private LockPatternUtils mLockPatternUtils;
-    private DeviceProvisionedController mDeviceProvisionedController;
-
-    // UI-specific methods
-
-    /**
-     * Create all windows necessary for the status bar (including navigation, overlay panels, etc)
-     * and add them to the window manager.
-     */
-    protected abstract void createAndAddWindows();
-
-    protected WindowManager mWindowManager;
-    protected IWindowManager mWindowManagerService;
-
-    protected Display mDisplay;
-
-    protected RecentsComponent mRecents;
-
-    protected int mZenMode;
-
-    // which notification is currently being longpress-examined by the user
-    private NotificationGuts mNotificationGutsExposed;
-
-    private KeyboardShortcuts mKeyboardShortcuts;
-
-    /**
-     * The {@link StatusBarState} of the status bar.
-     */
-    protected int mState;
-    protected boolean mBouncerShowing;
-    protected boolean mShowLockscreenNotifications;
-    protected boolean mAllowLockscreenRemoteInput;
-
-    protected NotificationShelf mNotificationShelf;
-    protected DismissView mDismissView;
-    protected EmptyShadeView mEmptyShadeView;
-
-    private NotificationClicker mNotificationClicker = new NotificationClicker();
-
-    protected AssistManager mAssistManager;
-
-    protected boolean mVrMode;
-
-    private Set<String> mNonBlockablePkgs;
-
-    @Override  // NotificationData.Environment
-    public boolean isDeviceProvisioned() {
-        return mDeviceProvisionedController.isDeviceProvisioned();
-    }
-
-    private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
-        @Override
-        public void onVrStateChanged(boolean enabled) {
-            mVrMode = enabled;
-        }
-    };
-
-    public boolean isDeviceInVrMode() {
-        return mVrMode;
-    }
-
-    private final DeviceProvisionedListener mDeviceProvisionedListener =
-            new DeviceProvisionedListener() {
-        @Override
-        public void onDeviceProvisionedChanged() {
-            updateNotifications();
-        }
-    };
-
-    protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
-        @Override
-        public void onChange(boolean selfChange) {
-            final int mode = Settings.Global.getInt(mContext.getContentResolver(),
-                    Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
-            setZenMode(mode);
-
-            updateLockscreenNotificationSetting();
-        }
-    };
-
-    private final ContentObserver mLockscreenSettingsObserver = new ContentObserver(mHandler) {
-        @Override
-        public void onChange(boolean selfChange) {
-            // We don't know which user changed LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS or
-            // LOCK_SCREEN_SHOW_NOTIFICATIONS, so we just dump our cache ...
-            mUsersAllowingPrivateNotifications.clear();
-            mUsersAllowingNotifications.clear();
-            // ... and refresh all the notifications
-            updateLockscreenNotificationSetting();
-            updateNotifications();
-        }
-    };
-
-    private RemoteViews.OnClickHandler mOnClickHandler = new RemoteViews.OnClickHandler() {
-        private final int[] mTmpInt2 = new int[2];
-
-        @Override
-        public boolean onClickHandler(
-                final View view, final PendingIntent pendingIntent, final Intent fillInIntent) {
-            view.getLocationInWindow(mTmpInt2);
-            wakeUpIfDozing(SystemClock.uptimeMillis(), new PointF(
-                    mTmpInt2[0] + view.getWidth() / 2, mTmpInt2[1] + view.getHeight() / 2));
-
-
-            if (handleRemoteInput(view, pendingIntent, fillInIntent)) {
-                return true;
-            }
-
-            if (DEBUG) {
-                Log.v(TAG, "Notification click handler invoked for intent: " + pendingIntent);
-            }
-            logActionClick(view);
-            // The intent we are sending is for the application, which
-            // won't have permission to immediately start an activity after
-            // the user switches to home.  We know it is safe to do at this
-            // point, so make sure new activity switches are now allowed.
-            try {
-                ActivityManager.getService().resumeAppSwitches();
-            } catch (RemoteException e) {
-            }
-            final boolean isActivity = pendingIntent.isActivity();
-            if (isActivity) {
-                final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
-                final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
-                        mContext, pendingIntent.getIntent(), mCurrentUserId);
-                dismissKeyguardThenExecute(new OnDismissAction() {
-                    @Override
-                    public boolean onDismiss() {
-                        try {
-                            ActivityManager.getService().resumeAppSwitches();
-                        } catch (RemoteException e) {
-                        }
-
-                        boolean handled = superOnClickHandler(view, pendingIntent, fillInIntent);
-
-                        // close the shade if it was open
-                        if (handled) {
-                            animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
-                                    true /* force */);
-                            visibilityChanged(false);
-                            mAssistManager.hideAssist();
-                        }
-
-                        // Wait for activity start.
-                        return handled;
-                    }
-                }, afterKeyguardGone);
-                return true;
-            } else {
-                return superOnClickHandler(view, pendingIntent, fillInIntent);
-            }
-        }
-
-        private void logActionClick(View view) {
-            ViewParent parent = view.getParent();
-            String key = getNotificationKeyForParent(parent);
-            if (key == null) {
-                Log.w(TAG, "Couldn't determine notification for click.");
-                return;
-            }
-            int index = -1;
-            // If this is a default template, determine the index of the button.
-            if (view.getId() == com.android.internal.R.id.action0 &&
-                    parent != null && parent instanceof ViewGroup) {
-                ViewGroup actionGroup = (ViewGroup) parent;
-                index = actionGroup.indexOfChild(view);
-            }
-            try {
-                mBarService.onNotificationActionClick(key, index);
-            } catch (RemoteException e) {
-                // Ignore
-            }
-        }
-
-        private String getNotificationKeyForParent(ViewParent parent) {
-            while (parent != null) {
-                if (parent instanceof ExpandableNotificationRow) {
-                    return ((ExpandableNotificationRow) parent).getStatusBarNotification().getKey();
-                }
-                parent = parent.getParent();
-            }
-            return null;
-        }
-
-        private boolean superOnClickHandler(View view, PendingIntent pendingIntent,
-                Intent fillInIntent) {
-            return super.onClickHandler(view, pendingIntent, fillInIntent,
-                    StackId.FULLSCREEN_WORKSPACE_STACK_ID);
-        }
-
-        private boolean handleRemoteInput(View view, PendingIntent pendingIntent, Intent fillInIntent) {
-            Object tag = view.getTag(com.android.internal.R.id.remote_input_tag);
-            RemoteInput[] inputs = null;
-            if (tag instanceof RemoteInput[]) {
-                inputs = (RemoteInput[]) tag;
-            }
-
-            if (inputs == null) {
-                return false;
-            }
-
-            RemoteInput input = null;
-
-            for (RemoteInput i : inputs) {
-                if (i.getAllowFreeFormInput()) {
-                    input = i;
-                }
-            }
-
-            if (input == null) {
-                return false;
-            }
-
-            ViewParent p = view.getParent();
-            RemoteInputView riv = null;
-            while (p != null) {
-                if (p instanceof View) {
-                    View pv = (View) p;
-                    if (pv.isRootNamespace()) {
-                        riv = (RemoteInputView) pv.findViewWithTag(RemoteInputView.VIEW_TAG);
-                        break;
-                    }
-                }
-                p = p.getParent();
-            }
-            ExpandableNotificationRow row = null;
-            while (p != null) {
-                if (p instanceof ExpandableNotificationRow) {
-                    row = (ExpandableNotificationRow) p;
-                    break;
-                }
-                p = p.getParent();
-            }
-
-            if (riv == null || row == null) {
-                return false;
-            }
-
-            row.setUserExpanded(true);
-
-            if (!mAllowLockscreenRemoteInput) {
-                final int userId = pendingIntent.getCreatorUserHandle().getIdentifier();
-                if (isLockscreenPublicMode(userId)) {
-                    onLockedRemoteInput(row, view);
-                    return true;
-                }
-                if (mUserManager.getUserInfo(userId).isManagedProfile()
-                        && mKeyguardManager.isDeviceLocked(userId)) {
-                    onLockedWorkRemoteInput(userId, row, view);
-                    return true;
-                }
-            }
-
-            int width = view.getWidth();
-            if (view instanceof TextView) {
-                // Center the reveal on the text which might be off-center from the TextView
-                TextView tv = (TextView) view;
-                if (tv.getLayout() != null) {
-                    int innerWidth = (int) tv.getLayout().getLineWidth(0);
-                    innerWidth += tv.getCompoundPaddingLeft() + tv.getCompoundPaddingRight();
-                    width = Math.min(width, innerWidth);
-                }
-            }
-            int cx = view.getLeft() + width / 2;
-            int cy = view.getTop() + view.getHeight() / 2;
-            int w = riv.getWidth();
-            int h = riv.getHeight();
-            int r = Math.max(
-                    Math.max(cx + cy, cx + (h - cy)),
-                    Math.max((w - cx) + cy, (w - cx) + (h - cy)));
-
-            riv.setRevealParameters(cx, cy, r);
-            riv.setPendingIntent(pendingIntent);
-            riv.setRemoteInput(inputs, input);
-            riv.focusAnimated();
-
-            return true;
-        }
-
-    };
-
-    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (Intent.ACTION_USER_SWITCHED.equals(action)) {
-                mCurrentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
-                updateCurrentProfilesCache();
-                if (true) Log.v(TAG, "userId " + mCurrentUserId + " is in the house");
-
-                updateLockscreenNotificationSetting();
-
-                userSwitched(mCurrentUserId);
-            } else if (Intent.ACTION_USER_ADDED.equals(action)) {
-                updateCurrentProfilesCache();
-            } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
-                List<ActivityManager.RecentTaskInfo> recentTask = null;
-                try {
-                    recentTask = ActivityManager.getService().getRecentTasks(1,
-                            ActivityManager.RECENT_WITH_EXCLUDED
-                            | ActivityManager.RECENT_INCLUDE_PROFILES,
-                            mCurrentUserId).getList();
-                } catch (RemoteException e) {
-                    // Abandon hope activity manager not running.
-                }
-                if (recentTask != null && recentTask.size() > 0) {
-                    UserInfo user = mUserManager.getUserInfo(recentTask.get(0).userId);
-                    if (user != null && user.isManagedProfile()) {
-                        Toast toast = Toast.makeText(mContext,
-                                R.string.managed_profile_foreground_toast,
-                                Toast.LENGTH_SHORT);
-                        TextView text = (TextView) toast.getView().findViewById(
-                                android.R.id.message);
-                        text.setCompoundDrawablesRelativeWithIntrinsicBounds(
-                                R.drawable.stat_sys_managed_profile_status, 0, 0, 0);
-                        int paddingPx = mContext.getResources().getDimensionPixelSize(
-                                R.dimen.managed_profile_toast_padding);
-                        text.setCompoundDrawablePadding(paddingPx);
-                        toast.show();
-                    }
-                }
-            } else if (BANNER_ACTION_CANCEL.equals(action) || BANNER_ACTION_SETUP.equals(action)) {
-                NotificationManager noMan = (NotificationManager)
-                        mContext.getSystemService(Context.NOTIFICATION_SERVICE);
-                noMan.cancel(SystemMessage.NOTE_HIDDEN_NOTIFICATIONS);
-
-                Settings.Secure.putInt(mContext.getContentResolver(),
-                        Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0);
-                if (BANNER_ACTION_SETUP.equals(action)) {
-                    animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
-                            true /* force */);
-                    mContext.startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_REDACTION)
-                            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
-
-                    );
-                }
-            } else if (NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION.equals(action)) {
-                final IntentSender intentSender = intent.getParcelableExtra(Intent.EXTRA_INTENT);
-                final String notificationKey = intent.getStringExtra(Intent.EXTRA_INDEX);
-                if (intentSender != null) {
-                    try {
-                        mContext.startIntentSender(intentSender, null, 0, 0, 0);
-                    } catch (IntentSender.SendIntentException e) {
-                        /* ignore */
-                    }
-                }
-                if (notificationKey != null) {
-                    try {
-                        mBarService.onNotificationClick(notificationKey);
-                    } catch (RemoteException e) {
-                        /* ignore */
-                    }
-                }
-            }
-        }
-    };
-
-    private final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            final String action = intent.getAction();
-            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
-
-            if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action) &&
-                    isCurrentProfile(getSendingUserId())) {
-                mUsersAllowingPrivateNotifications.clear();
-                updateLockscreenNotificationSetting();
-                updateNotifications();
-            } else if (Intent.ACTION_DEVICE_LOCKED_CHANGED.equals(action)) {
-                if (userId != mCurrentUserId && isCurrentProfile(userId)) {
-                    onWorkChallengeChanged();
-                }
-            }
-        }
-    };
-
-    private final NotificationListenerService mNotificationListener =
-            new NotificationListenerService() {
-        @Override
-        public void onListenerConnected() {
-            if (DEBUG) Log.d(TAG, "onListenerConnected");
-            final StatusBarNotification[] notifications = getActiveNotifications();
-            if (notifications == null) {
-                Log.w(TAG, "onListenerConnected unable to get active notifications.");
-                return;
-            }
-            final RankingMap currentRanking = getCurrentRanking();
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    for (StatusBarNotification sbn : notifications) {
-                        addNotification(sbn, currentRanking, null /* oldEntry */);
-                    }
-                }
-            });
-        }
-
-        @Override
-        public void onNotificationPosted(final StatusBarNotification sbn,
-                final RankingMap rankingMap) {
-            if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn);
-            if (sbn != null) {
-                mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        processForRemoteInput(sbn.getNotification());
-                        String key = sbn.getKey();
-                        mKeysKeptForRemoteInput.remove(key);
-                        boolean isUpdate = mNotificationData.get(key) != null;
-                        // In case we don't allow child notifications, we ignore children of
-                        // notifications that have a summary, since we're not going to show them
-                        // anyway. This is true also when the summary is canceled,
-                        // because children are automatically canceled by NoMan in that case.
-                        if (!ENABLE_CHILD_NOTIFICATIONS
-                            && mGroupManager.isChildInGroupWithSummary(sbn)) {
-                            if (DEBUG) {
-                                Log.d(TAG, "Ignoring group child due to existing summary: " + sbn);
-                            }
-
-                            // Remove existing notification to avoid stale data.
-                            if (isUpdate) {
-                                removeNotification(key, rankingMap);
-                            } else {
-                                mNotificationData.updateRanking(rankingMap);
-                            }
-                            return;
-                        }
-                        if (isUpdate) {
-                            updateNotification(sbn, rankingMap);
-                        } else {
-                            addNotification(sbn, rankingMap, null /* oldEntry */);
-                        }
-                    }
-                });
-            }
-        }
-
-        @Override
-        public void onNotificationRemoved(StatusBarNotification sbn,
-                final RankingMap rankingMap) {
-            if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn);
-            if (sbn != null) {
-                final String key = sbn.getKey();
-                mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        removeNotification(key, rankingMap);
-                    }
-                });
-            }
-        }
-
-        @Override
-        public void onNotificationRankingUpdate(final RankingMap rankingMap) {
-            if (DEBUG) Log.d(TAG, "onRankingUpdate");
-            if (rankingMap != null) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    updateNotificationRanking(rankingMap);
-                }
-            });
-        }                            }
-
-    };
-
-    private void updateCurrentProfilesCache() {
-        synchronized (mCurrentProfiles) {
-            mCurrentProfiles.clear();
-            if (mUserManager != null) {
-                for (UserInfo user : mUserManager.getProfiles(mCurrentUserId)) {
-                    mCurrentProfiles.put(user.id, user);
-                }
-            }
-        }
-    }
-
-    public void start() {
-        mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
-        mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
-        mDisplay = mWindowManager.getDefaultDisplay();
-        mDevicePolicyManager = (DevicePolicyManager)mContext.getSystemService(
-                Context.DEVICE_POLICY_SERVICE);
-
-        mNotificationData = new NotificationData(this);
-
-        mAccessibilityManager = (AccessibilityManager)
-                mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
-
-        mDreamManager = IDreamManager.Stub.asInterface(
-                ServiceManager.checkService(DreamService.DREAM_SERVICE));
-        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
-
-        mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
-        mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Global.getUriFor(Settings.Global.ZEN_MODE), false,
-                mSettingsObserver);
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS), false,
-                mLockscreenSettingsObserver,
-                UserHandle.USER_ALL);
-        if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
-            mContext.getContentResolver().registerContentObserver(
-                    Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT),
-                    false,
-                    mSettingsObserver,
-                    UserHandle.USER_ALL);
-        }
-
-        mContext.getContentResolver().registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS),
-                true,
-                mLockscreenSettingsObserver,
-                UserHandle.USER_ALL);
-
-        mBarService = IStatusBarService.Stub.asInterface(
-                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
-
-        mRecents = getComponent(Recents.class);
-
-        final Configuration currentConfig = mContext.getResources().getConfiguration();
-        mLocale = currentConfig.locale;
-        mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(mLocale);
-        mFontScale = currentConfig.fontScale;
-        mDensity = currentConfig.densityDpi;
-
-        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-        mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
-        mLockPatternUtils = new LockPatternUtils(mContext);
-
-        // Connect in to the status bar manager service
-        mCommandQueue = getComponent(CommandQueue.class);
-        mCommandQueue.addCallbacks(this);
-
-        int[] switches = new int[9];
-        ArrayList<IBinder> binders = new ArrayList<IBinder>();
-        ArrayList<String> iconSlots = new ArrayList<>();
-        ArrayList<StatusBarIcon> icons = new ArrayList<>();
-        Rect fullscreenStackBounds = new Rect();
-        Rect dockedStackBounds = new Rect();
-        try {
-            mBarService.registerStatusBar(mCommandQueue, iconSlots, icons, switches, binders,
-                    fullscreenStackBounds, dockedStackBounds);
-        } catch (RemoteException ex) {
-            // If the system process isn't there we're doomed anyway.
-        }
-
-        createAndAddWindows();
-
-        mSettingsObserver.onChange(false); // set up
-        disable(switches[0], switches[6], false /* animate */);
-        setSystemUiVisibility(switches[1], switches[7], switches[8], 0xffffffff,
-                fullscreenStackBounds, dockedStackBounds);
-        topAppWindowChanged(switches[2] != 0);
-        // StatusBarManagerService has a back up of IME token and it's restored here.
-        setImeWindowStatus(binders.get(0), switches[3], switches[4], switches[5] != 0);
-
-        // Set up the initial icon state
-        int N = iconSlots.size();
-        int viewIndex = 0;
-        for (int i=0; i < N; i++) {
-            setIcon(iconSlots.get(i), icons.get(i));
-        }
-
-        // Set up the initial notification state.
-        try {
-            mNotificationListener.registerAsSystemService(mContext,
-                    new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()),
-                    UserHandle.USER_ALL);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Unable to register notification listener", e);
-        }
-
-
-        if (DEBUG) {
-            Log.d(TAG, String.format(
-                    "init: icons=%d disabled=0x%08x lights=0x%08x menu=0x%08x imeButton=0x%08x",
-                   icons.size(),
-                   switches[0],
-                   switches[1],
-                   switches[2],
-                   switches[3]
-                   ));
-        }
-
-        mCurrentUserId = ActivityManager.getCurrentUser();
-        setHeadsUpUser(mCurrentUserId);
-
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_USER_SWITCHED);
-        filter.addAction(Intent.ACTION_USER_ADDED);
-        filter.addAction(Intent.ACTION_USER_PRESENT);
-        mContext.registerReceiver(mBroadcastReceiver, filter);
-
-        IntentFilter internalFilter = new IntentFilter();
-        internalFilter.addAction(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION);
-        internalFilter.addAction(BANNER_ACTION_CANCEL);
-        internalFilter.addAction(BANNER_ACTION_SETUP);
-        mContext.registerReceiver(mBroadcastReceiver, internalFilter, PERMISSION_SELF, null);
-
-        IntentFilter allUsersFilter = new IntentFilter();
-        allUsersFilter.addAction(
-                DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
-        allUsersFilter.addAction(Intent.ACTION_DEVICE_LOCKED_CHANGED);
-        mContext.registerReceiverAsUser(mAllUsersReceiver, UserHandle.ALL, allUsersFilter,
-                null, null);
-        updateCurrentProfilesCache();
-
-        IVrManager vrManager = IVrManager.Stub.asInterface(ServiceManager.getService("vrmanager"));
-        try {
-            vrManager.registerListener(mVrStateCallbacks);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Failed to register VR mode state listener: " + e);
-        }
-
-        mNonBlockablePkgs = new HashSet<String>();
-        Collections.addAll(mNonBlockablePkgs, mContext.getResources().getStringArray(
-                com.android.internal.R.array.config_nonBlockableNotificationPackages));
-    }
-
-    protected void notifyUserAboutHiddenNotifications() {
-        if (0 != Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 1)) {
-            Log.d(TAG, "user hasn't seen notification about hidden notifications");
-            if (!mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) {
-                Log.d(TAG, "insecure lockscreen, skipping notification");
-                Settings.Secure.putInt(mContext.getContentResolver(),
-                        Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0);
-                return;
-            }
-            Log.d(TAG, "disabling lockecreen notifications and alerting the user");
-            // disable lockscreen notifications until user acts on the banner.
-            Settings.Secure.putInt(mContext.getContentResolver(),
-                    Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0);
-            Settings.Secure.putInt(mContext.getContentResolver(),
-                    Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0);
-
-            final String packageName = mContext.getPackageName();
-            PendingIntent cancelIntent = PendingIntent.getBroadcast(mContext, 0,
-                    new Intent(BANNER_ACTION_CANCEL).setPackage(packageName),
-                    PendingIntent.FLAG_CANCEL_CURRENT);
-            PendingIntent setupIntent = PendingIntent.getBroadcast(mContext, 0,
-                    new Intent(BANNER_ACTION_SETUP).setPackage(packageName),
-                    PendingIntent.FLAG_CANCEL_CURRENT);
-
-            final int colorRes = com.android.internal.R.color.system_notification_accent_color;
-            Notification.Builder note = new Notification.Builder(mContext)
-                    .setSmallIcon(R.drawable.ic_android)
-                    .setContentTitle(mContext.getString(R.string.hidden_notifications_title))
-                    .setContentText(mContext.getString(R.string.hidden_notifications_text))
-                    .setPriority(Notification.PRIORITY_HIGH)
-                    .setOngoing(true)
-                    .setColor(mContext.getColor(colorRes))
-                    .setContentIntent(setupIntent)
-                    .addAction(R.drawable.ic_close,
-                            mContext.getString(R.string.hidden_notifications_cancel),
-                            cancelIntent)
-                    .addAction(R.drawable.ic_settings,
-                            mContext.getString(R.string.hidden_notifications_setup),
-                            setupIntent);
-            overrideNotificationAppName(mContext, note);
-
-            NotificationManager noMan =
-                    (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
-            noMan.notify(SystemMessage.NOTE_HIDDEN_NOTIFICATIONS, note.build());
-        }
-    }
-
-    public void userSwitched(int newUserId) {
-        setHeadsUpUser(newUserId);
-    }
-
-    protected abstract void setHeadsUpUser(int newUserId);
-
-    @Override  // NotificationData.Environment
-    public boolean isNotificationForCurrentProfiles(StatusBarNotification n) {
-        final int thisUserId = mCurrentUserId;
-        final int notificationUserId = n.getUserId();
-        if (DEBUG && MULTIUSER_DEBUG) {
-            Log.v(TAG, String.format("%s: current userid: %d, notification userid: %d",
-                    n, thisUserId, notificationUserId));
-        }
-        return isCurrentProfile(notificationUserId);
-    }
-
-    protected void setNotificationShown(StatusBarNotification n) {
-        setNotificationsShown(new String[]{n.getKey()});
-    }
-
-    protected void setNotificationsShown(String[] keys) {
-        try {
-            mNotificationListener.setNotificationsShown(keys);
-        } catch (RuntimeException e) {
-            Log.d(TAG, "failed setNotificationsShown: ", e);
-        }
-    }
-
-    protected boolean isCurrentProfile(int userId) {
-        synchronized (mCurrentProfiles) {
-            return userId == UserHandle.USER_ALL || mCurrentProfiles.get(userId) != null;
-        }
-    }
-
-    @Override
-    public String getCurrentMediaNotificationKey() {
-        return null;
-    }
-
-    @Override
-    public NotificationGroupManager getGroupManager() {
-        return mGroupManager;
-    }
-
-    /**
-     * Takes the necessary steps to prepare the status bar for starting an activity, then starts it.
-     * @param action A dismiss action that is called if it's safe to start the activity.
-     * @param afterKeyguardGone Whether the action should be executed after the Keyguard is gone.
-     */
-    protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) {
-        action.onDismiss();
-    }
-
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        final float fontScale = newConfig.fontScale;
-        final int density = newConfig.densityDpi;
-        if (density != mDensity || mFontScale != fontScale) {
-            onDensityOrFontScaleChanged();
-            mDensity = density;
-            mFontScale = fontScale;
-        }
-    }
-
-    protected void onDensityOrFontScaleChanged() {
-        ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
-        for (int i = 0; i < activeNotifications.size(); i++) {
-            Entry entry = activeNotifications.get(i);
-            boolean exposedGuts = entry.row.getGuts() == mNotificationGutsExposed;
-            entry.row.reInflateViews();
-            if (exposedGuts) {
-                mNotificationGutsExposed = entry.row.getGuts();
-                bindGuts(entry.row);
-            }
-            inflateViews(entry, mStackScroller);
-        }
-    }
-
-    protected void bindDismissRunnable(final ExpandableNotificationRow row) {
-        row.setOnDismissRunnable(() -> performRemoveNotification(row.getStatusBarNotification()));
-    }
-
-    protected void performRemoveNotification(StatusBarNotification n) {
-        final String pkg = n.getPackageName();
-        final String tag = n.getTag();
-        final int id = n.getId();
-        final int userId = n.getUserId();
-        try {
-            mBarService.onNotificationClear(pkg, tag, id, userId);
-            if (FORCE_REMOTE_INPUT_HISTORY
-                    && mKeysKeptForRemoteInput.contains(n.getKey())) {
-                mKeysKeptForRemoteInput.remove(n.getKey());
-            }
-            removeNotification(n.getKey(), null);
-
-        } catch (RemoteException ex) {
-            // system process is dead if we're here.
-        }
-    }
-
-
-    protected void applyColorsAndBackgrounds(StatusBarNotification sbn,
-            NotificationData.Entry entry) {
-
-        if (entry.getContentView().getId()
-                != com.android.internal.R.id.status_bar_latest_event_content) {
-            // Using custom RemoteViews
-            if (entry.targetSdk >= Build.VERSION_CODES.GINGERBREAD
-                    && entry.targetSdk < Build.VERSION_CODES.LOLLIPOP) {
-                entry.row.setShowingLegacyBackground(true);
-                entry.legacy = true;
-            }
-        }
-
-        entry.setIconTag(R.id.icon_is_pre_L, entry.targetSdk < Build.VERSION_CODES.LOLLIPOP);
-    }
-
-    public boolean isMediaNotification(NotificationData.Entry entry) {
-        // TODO: confirm that there's a valid media key
-        return entry.getExpandedContentView() != null &&
-               entry.getExpandedContentView()
-                       .findViewById(com.android.internal.R.id.media_actions) != null;
-    }
-
-    // The (i) button in the guts that links to the system notification settings for that app
-    private void startAppNotificationSettingsActivity(String packageName, final int appUid) {
-        final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
-        intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName);
-        intent.putExtra(Settings.EXTRA_APP_UID, appUid);
-        startNotificationGutsIntent(intent, appUid);
-    }
-
-    private void startNotificationGutsIntent(final Intent intent, final int appUid) {
-        dismissKeyguardThenExecute(new OnDismissAction() {
-            @Override
-            public boolean onDismiss() {
-                AsyncTask.execute(new Runnable() {
-                    public void run() {
-                        TaskStackBuilder.create(mContext)
-                                .addNextIntentWithParentStack(intent)
-                                .startActivities(getActivityOptions(),
-                                        new UserHandle(UserHandle.getUserId(appUid)));
-                    }
-                });
-                animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
-                return true;
-            }
-        }, false /* afterKeyguardGone */);
-    }
-
-    private void bindGuts(final ExpandableNotificationRow row) {
-        row.inflateGuts();
-        final StatusBarNotification sbn = row.getStatusBarNotification();
-        final NotificationChannel channel = row.getEntry().channel;
-        PackageManager pmUser = getPackageManagerForUser(mContext, sbn.getUser().getIdentifier());
-        row.setTag(sbn.getPackageName());
-        final NotificationGuts guts = row.getGuts();
-        guts.setClosedListener((NotificationGuts g) -> {
-            if (!row.isRemoved()) {
-                mStackScroller.onHeightChanged(row, !isPanelFullyCollapsed() /* needsAnimation */);
-            }
-            mNotificationGutsExposed = null;
-        });
-
-        final INotificationManager iNotificationManager = INotificationManager.Stub.asInterface(
-                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
-
-        final String pkg = sbn.getPackageName();
-        final NotificationGuts.OnSettingsClickListener onSettingsClick =
-                (View v, int appUid) -> {
-                    MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_INFO);
-                    guts.resetFalsingCheck();
-                    startAppNotificationSettingsActivity(pkg, appUid);
-                };
-        final View.OnClickListener onDoneClick =
-                (View v) -> {
-                    // If the user has security enabled, show challenge if the setting is changed.
-                    if (guts.hasImportanceChanged()
-                                && isLockscreenPublicMode(sbn.getUser().getIdentifier())
-                                && (mState == StatusBarState.KEYGUARD
-                                        || mState == StatusBarState.SHADE_LOCKED)) {
-                        OnDismissAction dismissAction = new OnDismissAction() {
-                            @Override
-                            public boolean onDismiss() {
-                                closeControls(row, guts, v);
-                                return true;
-                            }
-                        };
-                        onLockedNotificationImportanceChange(dismissAction);
-                    } else {
-                        closeControls(row, guts, v);
-                    }
-                };
-        guts.bindNotification(pmUser, iNotificationManager, sbn, channel,
-                onSettingsClick, onDoneClick, mNonBlockablePkgs);
-    }
-
-    private void closeControls(
-            ExpandableNotificationRow row, NotificationGuts guts, View done) {
-        guts.resetFalsingCheck();
-
-        int[] rowLocation = new int[2];
-        int[] doneLocation = new int[2];
-        row.getLocationOnScreen(rowLocation);
-        done.getLocationOnScreen(doneLocation);
-
-        final int centerX = done.getWidth() / 2;
-        final int centerY = done.getHeight() / 2;
-        final int x = doneLocation[0] - rowLocation[0] + centerX;
-        final int y = doneLocation[1] - rowLocation[1] + centerY;
-        dismissPopups(x, y);
-    }
-
-    protected SwipeHelper.LongPressListener getNotificationLongClicker() {
-        return new SwipeHelper.LongPressListener() {
-            @Override
-            public boolean onLongPress(View v, final int x, final int y) {
-                if (!(v instanceof ExpandableNotificationRow)) {
-                    return false;
-                }
-                if (v.getWindowToken() == null) {
-                    Log.e(TAG, "Trying to show notification guts, but not attached to window");
-                    return false;
-                }
-
-                final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
-                bindGuts(row);
-
-                // Assume we are a status_bar_notification_row
-                final NotificationGuts guts = row.getGuts();
-                if (guts == null) {
-                    // This view has no guts. Examples are the more card or the dismiss all view
-                    return false;
-                }
-
-                // Already showing?
-                if (guts.getVisibility() == View.VISIBLE) {
-                    dismissPopups(x, y);
-                    return false;
-                }
-
-                MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_CONTROLS);
-
-                // ensure that it's laid but not visible until actually laid out
-                guts.setVisibility(View.INVISIBLE);
-                // Post to ensure the the guts are properly laid out.
-                guts.post(new Runnable() {
-                    public void run() {
-                        if (row.getWindowToken() == null) {
-                            Log.e(TAG, "Trying to show notification guts, but not attached to "
-                                    + "window");
-                            return;
-                        }
-                        dismissPopups(-1 /* x */, -1 /* y */, false /* resetGear */,
-                                false /* animate */);
-                        guts.setVisibility(View.VISIBLE);
-                        final double horz = Math.max(guts.getWidth() - x, x);
-                        final double vert = Math.max(guts.getHeight() - y, y);
-                        final float r = (float) Math.hypot(horz, vert);
-                        final Animator a
-                                = ViewAnimationUtils.createCircularReveal(guts, x, y, 0, r);
-                        a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
-                        a.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
-                        a.addListener(new AnimatorListenerAdapter() {
-                            @Override
-                            public void onAnimationEnd(Animator animation) {
-                                super.onAnimationEnd(animation);
-                                // Move the notification view back over the gear
-                                row.resetTranslation();
-                            }
-                        });
-                        a.start();
-                        guts.setExposed(true /* exposed */,
-                                mState == StatusBarState.KEYGUARD /* needsFalsingProtection */);
-                        row.closeRemoteInput();
-                        mStackScroller.onHeightChanged(row, true /* needsAnimation */);
-                        mNotificationGutsExposed = guts;
-                    }
-                });
-                return true;
-            }
-        };
-    }
-
-    /**
-     * Returns the exposed NotificationGuts or null if none are exposed.
-     */
-    public NotificationGuts getExposedGuts() {
-        return mNotificationGutsExposed;
-    }
-
-    public void dismissPopups() {
-        dismissPopups(-1 /* x */, -1 /* y */, true /* resetGear */, false /* animate */);
-    }
-
-    private void dismissPopups(int x, int y) {
-        dismissPopups(x, y, true /* resetGear */, false /* animate */);
-    }
-
-    public void dismissPopups(int x, int y, boolean resetGear, boolean animate) {
-        if (mNotificationGutsExposed != null) {
-            mNotificationGutsExposed.closeControls(x, y, true /* save */);
-        }
-        if (resetGear) {
-            mStackScroller.resetExposedGearView(animate, true /* force */);
-        }
-    }
-
-    @Override
-    public void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
-        int msg = MSG_SHOW_RECENT_APPS;
-        mHandler.removeMessages(msg);
-        mHandler.obtainMessage(msg, triggeredFromAltTab ? 1 : 0, fromHome ? 1 : 0).sendToTarget();
-    }
-
-    @Override
-    public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
-        int msg = MSG_HIDE_RECENT_APPS;
-        mHandler.removeMessages(msg);
-        mHandler.obtainMessage(msg, triggeredFromAltTab ? 1 : 0,
-                triggeredFromHomeKey ? 1 : 0).sendToTarget();
-    }
-
-    @Override
-    public void toggleRecentApps() {
-        toggleRecents();
-    }
-
-    @Override
-    public void toggleSplitScreen() {
-        toggleSplitScreenMode(-1 /* metricsDockAction */, -1 /* metricsUndockAction */);
-    }
-
-    @Override
-    public void preloadRecentApps() {
-        int msg = MSG_PRELOAD_RECENT_APPS;
-        mHandler.removeMessages(msg);
-        mHandler.sendEmptyMessage(msg);
-    }
-
-    @Override
-    public void cancelPreloadRecentApps() {
-        int msg = MSG_CANCEL_PRELOAD_RECENT_APPS;
-        mHandler.removeMessages(msg);
-        mHandler.sendEmptyMessage(msg);
-    }
-
-    @Override
-    public void dismissKeyboardShortcutsMenu() {
-        int msg = MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU;
-        mHandler.removeMessages(msg);
-        mHandler.sendEmptyMessage(msg);
-    }
-
-    @Override
-    public void toggleKeyboardShortcutsMenu(int deviceId) {
-        int msg = MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU;
-        mHandler.removeMessages(msg);
-        mHandler.obtainMessage(msg, deviceId, 0).sendToTarget();
-    }
-
-    /** Jumps to the next affiliated task in the group. */
-    public void showNextAffiliatedTask() {
-        int msg = MSG_SHOW_NEXT_AFFILIATED_TASK;
-        mHandler.removeMessages(msg);
-        mHandler.sendEmptyMessage(msg);
-    }
-
-    /** Jumps to the previous affiliated task in the group. */
-    public void showPreviousAffiliatedTask() {
-        int msg = MSG_SHOW_PREV_AFFILIATED_TASK;
-        mHandler.removeMessages(msg);
-        mHandler.sendEmptyMessage(msg);
-    }
-
-    protected H createHandler() {
-         return new H();
-    }
-
-    protected void sendCloseSystemWindows(String reason) {
-        try {
-            ActivityManager.getService().closeSystemDialogs(reason);
-        } catch (RemoteException e) {
-        }
-    }
-
-    protected abstract View getStatusBarView();
-
-    /**
-     * Toggle docking the app window
-     *
-     * @param metricsDockAction the action to log when docking is successful, or -1 to not log
-     *                          anything on successful docking
-     * @param metricsUndockAction the action to log when undocking, or -1 to not log anything when
-     *                            undocking
-     * @return true if toggle split screen was successful
-     */
-    protected abstract boolean toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction);
-
-    /** Proxy for RecentsComponent */
-
-    protected void showRecents(boolean triggeredFromAltTab, boolean fromHome) {
-        if (mRecents != null) {
-            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
-            mRecents.showRecents(triggeredFromAltTab, fromHome);
-        }
-    }
-
-    protected void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
-        if (mRecents != null) {
-            mRecents.hideRecents(triggeredFromAltTab, triggeredFromHomeKey);
-        }
-    }
-
-    protected void toggleRecents() {
-        if (mRecents != null) {
-            mRecents.toggleRecents(mDisplay);
-        }
-    }
-
-    protected void preloadRecents() {
-        if (mRecents != null) {
-            mRecents.preloadRecents();
-        }
-    }
-
-    protected void toggleKeyboardShortcuts(int deviceId) {
-        KeyboardShortcuts.toggle(mContext, deviceId);
-    }
-
-    protected void dismissKeyboardShortcuts() {
-        KeyboardShortcuts.dismiss();
-    }
-
-    protected void cancelPreloadingRecents() {
-        if (mRecents != null) {
-            mRecents.cancelPreloadingRecents();
-        }
-    }
-
-    protected void showRecentsNextAffiliatedTask() {
-        if (mRecents != null) {
-            mRecents.showNextAffiliatedTask();
-        }
-    }
-
-    protected void showRecentsPreviousAffiliatedTask() {
-        if (mRecents != null) {
-            mRecents.showPrevAffiliatedTask();
-        }
-    }
-
-    /**
-     * If there is an active heads-up notification and it has a fullscreen intent, fire it now.
-     */
-    public abstract void maybeEscalateHeadsUp();
-
-    /**
-     * Save the current "public" (locked and secure) state of the lockscreen.
-     */
-    public void setLockscreenPublicMode(boolean publicMode, int userId) {
-        mLockscreenPublicMode.put(userId, publicMode);
-    }
-
-    public boolean isLockscreenPublicMode(int userId) {
-        return mLockscreenPublicMode.get(userId, false);
-    }
-
-    protected void onWorkChallengeChanged() {}
-
-    /**
-     * Has the given user chosen to allow notifications to be shown even when the lockscreen is in
-     * "public" (secure & locked) mode?
-     */
-    public boolean userAllowsNotificationsInPublic(int userHandle) {
-        if (userHandle == UserHandle.USER_ALL) {
-            return true;
-        }
-
-        if (mUsersAllowingNotifications.indexOfKey(userHandle) < 0) {
-            final boolean allowed = 0 != Settings.Secure.getIntForUser(
-                    mContext.getContentResolver(),
-                    Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, userHandle);
-            mUsersAllowingNotifications.append(userHandle, allowed);
-            return allowed;
-        }
-
-        return mUsersAllowingNotifications.get(userHandle);
-    }
-
-    /**
-     * Has the given user chosen to allow their private (full) notifications to be shown even
-     * when the lockscreen is in "public" (secure & locked) mode?
-     */
-    public boolean userAllowsPrivateNotificationsInPublic(int userHandle) {
-        if (userHandle == UserHandle.USER_ALL) {
-            return true;
-        }
-
-        if (mUsersAllowingPrivateNotifications.indexOfKey(userHandle) < 0) {
-            final boolean allowedByUser = 0 != Settings.Secure.getIntForUser(
-                    mContext.getContentResolver(),
-                    Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, userHandle);
-            final boolean allowedByDpm = adminAllowsUnredactedNotifications(userHandle);
-            final boolean allowed = allowedByUser && allowedByDpm;
-            mUsersAllowingPrivateNotifications.append(userHandle, allowed);
-            return allowed;
-        }
-
-        return mUsersAllowingPrivateNotifications.get(userHandle);
-    }
-
-    private boolean adminAllowsUnredactedNotifications(int userHandle) {
-        if (userHandle == UserHandle.USER_ALL) {
-            return true;
-        }
-        final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures(null /* admin */,
-                    userHandle);
-        return (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) == 0;
-    }
-
-    /**
-     * Returns true if we're on a secure lockscreen and the user wants to hide notification data.
-     * If so, notifications should be hidden.
-     */
-    @Override  // NotificationData.Environment
-    public boolean shouldHideNotifications(int userId) {
-        return isLockscreenPublicMode(userId) && !userAllowsNotificationsInPublic(userId)
-                || (userId != mCurrentUserId && shouldHideNotifications(mCurrentUserId));
-    }
-
-    /**
-     * Returns true if we're on a secure lockscreen and the user wants to hide notifications via
-     * package-specific override.
-     */
-    @Override // NotificationDate.Environment
-    public boolean shouldHideNotifications(String key) {
-        return isLockscreenPublicMode(mCurrentUserId)
-                && mNotificationData.getVisibilityOverride(key) == Notification.VISIBILITY_SECRET;
-    }
-
-    /**
-     * Returns true if we're on a secure lockscreen.
-     */
-    @Override  // NotificationData.Environment
-    public boolean isSecurelyLocked(int userId) {
-        return isLockscreenPublicMode(userId);
-    }
-
-    public void onNotificationClear(StatusBarNotification notification) {
-        try {
-            mBarService.onNotificationClear(
-                    notification.getPackageName(),
-                    notification.getTag(),
-                    notification.getId(),
-                    notification.getUserId());
-        } catch (android.os.RemoteException ex) {
-            // oh well
-        }
-    }
-
-    /**
-     * Called when the notification panel layouts
-     */
-    public void onPanelLaidOut() {
-        if (mState == StatusBarState.KEYGUARD) {
-            // Since the number of notifications is determined based on the height of the view, we
-            // need to update them.
-            int maxBefore = getMaxKeyguardNotifications(false /* recompute */);
-            int maxNotifications = getMaxKeyguardNotifications(true /* recompute */);
-            if (maxBefore != maxNotifications) {
-                updateRowStates();
-            }
-        }
-    }
-
-    protected void onLockedNotificationImportanceChange(OnDismissAction dismissAction) {}
-
-    protected void onLockedRemoteInput(ExpandableNotificationRow row, View clickedView) {}
-
-    protected void onLockedWorkRemoteInput(int userId, ExpandableNotificationRow row,
-            View clicked) {}
-
-    @Override
-    public void onExpandClicked(Entry clickedEntry, boolean nowExpanded) {
-    }
-
-    protected class H extends Handler {
-        public void handleMessage(Message m) {
-            switch (m.what) {
-             case MSG_SHOW_RECENT_APPS:
-                 showRecents(m.arg1 > 0, m.arg2 != 0);
-                 break;
-             case MSG_HIDE_RECENT_APPS:
-                 hideRecents(m.arg1 > 0, m.arg2 > 0);
-                 break;
-             case MSG_TOGGLE_RECENTS_APPS:
-                 toggleRecents();
-                 break;
-             case MSG_PRELOAD_RECENT_APPS:
-                  preloadRecents();
-                  break;
-             case MSG_CANCEL_PRELOAD_RECENT_APPS:
-                  cancelPreloadingRecents();
-                  break;
-             case MSG_SHOW_NEXT_AFFILIATED_TASK:
-                  showRecentsNextAffiliatedTask();
-                  break;
-             case MSG_SHOW_PREV_AFFILIATED_TASK:
-                  showRecentsPreviousAffiliatedTask();
-                  break;
-             case MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU:
-                  toggleKeyboardShortcuts(m.arg1);
-                  break;
-             case MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU:
-                  dismissKeyboardShortcuts();
-                  break;
-            }
-        }
-    }
-
-    protected void workAroundBadLayerDrawableOpacity(View v) {
-    }
-
-    protected boolean inflateViews(Entry entry, ViewGroup parent) {
-        PackageManager pmUser = getPackageManagerForUser(mContext,
-                entry.notification.getUser().getIdentifier());
-
-        final StatusBarNotification sbn = entry.notification;
-        boolean isLowPriority = mNotificationData.isAmbient(sbn.getKey());
-        try {
-            entry.cacheContentViews(mContext, null, isLowPriority);
-        } catch (RuntimeException e) {
-            Log.e(TAG, "Unable to get notification remote views", e);
-            return false;
-        }
-
-        final RemoteViews contentView = entry.cachedContentView;
-        final RemoteViews bigContentView = entry.cachedBigContentView;
-        final RemoteViews headsUpContentView = entry.cachedHeadsUpContentView;
-        final RemoteViews publicContentView = entry.cachedPublicContentView;
-        final RemoteViews ambientContentView = entry.cachedAmbientContentView;
-
-        if (contentView == null) {
-            Log.v(TAG, "no contentView for: " + sbn.getNotification());
-            return false;
-        }
-
-        if (DEBUG) {
-            Log.v(TAG, "publicContentView: " + publicContentView);
-        }
-
-        ExpandableNotificationRow row;
-
-        // Stash away previous user expansion state so we can restore it at
-        // the end.
-        boolean hasUserChangedExpansion = false;
-        boolean userExpanded = false;
-        boolean userLocked = false;
-
-        if (entry.row != null) {
-            row = entry.row;
-            hasUserChangedExpansion = row.hasUserChangedExpansion();
-            userExpanded = row.isUserExpanded();
-            userLocked = row.isUserLocked();
-            entry.reset();
-            if (hasUserChangedExpansion) {
-                row.setUserExpanded(userExpanded);
-            }
-        } else {
-            // create the row view
-            LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
-                    Context.LAYOUT_INFLATER_SERVICE);
-            row = (ExpandableNotificationRow) inflater.inflate(R.layout.status_bar_notification_row,
-                    parent, false);
-            row.setExpansionLogger(this, entry.notification.getKey());
-            row.setGroupManager(mGroupManager);
-            row.setHeadsUpManager(mHeadsUpManager);
-            row.setRemoteInputController(mRemoteInputController);
-            row.setOnExpandClickListener(this);
-
-            // Get the app name.
-            // Note that Notification.Builder#bindHeaderAppName has similar logic
-            // but since this field is used in the guts, it must be accurate.
-            // Therefore we will only show the application label, or, failing that, the
-            // package name. No substitutions.
-            final String pkg = sbn.getPackageName();
-            String appname = pkg;
-            try {
-                final ApplicationInfo info = pmUser.getApplicationInfo(pkg,
-                        PackageManager.MATCH_UNINSTALLED_PACKAGES
-                                | PackageManager.MATCH_DISABLED_COMPONENTS);
-                if (info != null) {
-                    appname = String.valueOf(pmUser.getApplicationLabel(info));
-                }
-            } catch (NameNotFoundException e) {
-                // Do nothing
-            }
-            row.setAppName(appname);
-        }
-
-        workAroundBadLayerDrawableOpacity(row);
-        bindDismissRunnable(row);
-        row.setIsLowPriority(isLowPriority);
-
-        // NB: the large icon is now handled entirely by the template
-
-        // bind the click event to the content area
-        NotificationContentView contentContainer = row.getPrivateLayout();
-        NotificationContentView contentContainerPublic = row.getPublicLayout();
-
-        row.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
-        if (ENABLE_REMOTE_INPUT) {
-            row.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
-        }
-
-        mNotificationClicker.register(row, sbn);
-
-        // set up the adaptive layout
-        View contentViewLocal = null;
-        View bigContentViewLocal = null;
-        View headsUpContentViewLocal = null;
-        View publicViewLocal = null;
-        View ambientViewLocal = null;
-        try {
-            contentViewLocal = contentView.apply(
-                    sbn.getPackageContext(mContext),
-                    contentContainer,
-                    mOnClickHandler);
-            if (bigContentView != null) {
-                bigContentViewLocal = bigContentView.apply(
-                        sbn.getPackageContext(mContext),
-                        contentContainer,
-                        mOnClickHandler);
-            }
-            if (headsUpContentView != null) {
-                headsUpContentViewLocal = headsUpContentView.apply(
-                        sbn.getPackageContext(mContext),
-                        contentContainer,
-                        mOnClickHandler);
-            }
-            if (publicContentView != null) {
-                publicViewLocal = publicContentView.apply(
-                        sbn.getPackageContext(mContext),
-                        contentContainerPublic, mOnClickHandler);
-            }
-            if (ambientContentView != null) {
-                ambientViewLocal = ambientContentView.apply(
-                        sbn.getPackageContext(mContext),
-                        contentContainer, mOnClickHandler);
-            }
-
-            if (contentViewLocal != null) {
-                contentViewLocal.setIsRootNamespace(true);
-                contentContainer.setContractedChild(contentViewLocal);
-            }
-            if (bigContentViewLocal != null) {
-                bigContentViewLocal.setIsRootNamespace(true);
-                contentContainer.setExpandedChild(bigContentViewLocal);
-            }
-            if (headsUpContentViewLocal != null) {
-                headsUpContentViewLocal.setIsRootNamespace(true);
-                contentContainer.setHeadsUpChild(headsUpContentViewLocal);
-            }
-            if (publicViewLocal != null) {
-                publicViewLocal.setIsRootNamespace(true);
-                contentContainerPublic.setContractedChild(publicViewLocal);
-            }
-
-            if (ambientViewLocal != null) {
-                ambientViewLocal.setIsRootNamespace(true);
-                contentContainer.setAmbientChild(ambientViewLocal);
-            }
-        }
-        catch (RuntimeException e) {
-            final String ident = sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId());
-            Log.e(TAG, "couldn't inflate view for notification " + ident, e);
-            return false;
-        }
-
-        // Extract target SDK version.
-        try {
-            ApplicationInfo info = pmUser.getApplicationInfo(sbn.getPackageName(), 0);
-            entry.targetSdk = info.targetSdkVersion;
-        } catch (NameNotFoundException ex) {
-            Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex);
-        }
-        entry.autoRedacted = entry.notification.getNotification().publicVersion == null;
-
-        entry.row = row;
-        entry.row.setOnActivatedListener(this);
-        entry.row.setExpandable(bigContentViewLocal != null);
-
-        applyColorsAndBackgrounds(sbn, entry);
-
-        // Restore previous flags.
-        if (hasUserChangedExpansion) {
-            // Note: setUserExpanded() conveniently ignores calls with
-            //       userExpanded=true if !isExpandable().
-            row.setUserExpanded(userExpanded);
-        }
-        row.setUserLocked(userLocked);
-        row.onNotificationUpdated(entry);
-        return true;
-    }
-
-    /**
-     * Adds RemoteInput actions from the WearableExtender; to be removed once more apps support this
-     * via first-class API.
-     *
-     * TODO: Remove once enough apps specify remote inputs on their own.
-     */
-    private void processForRemoteInput(Notification n) {
-        if (!ENABLE_REMOTE_INPUT) return;
-
-        if (n.extras != null && n.extras.containsKey("android.wearable.EXTENSIONS") &&
-                (n.actions == null || n.actions.length == 0)) {
-            Notification.Action viableAction = null;
-            Notification.WearableExtender we = new Notification.WearableExtender(n);
-
-            List<Notification.Action> actions = we.getActions();
-            final int numActions = actions.size();
-
-            for (int i = 0; i < numActions; i++) {
-                Notification.Action action = actions.get(i);
-                if (action == null) {
-                    continue;
-                }
-                RemoteInput[] remoteInputs = action.getRemoteInputs();
-                if (remoteInputs == null) {
-                    continue;
-                }
-                for (RemoteInput ri : remoteInputs) {
-                    if (ri.getAllowFreeFormInput()) {
-                        viableAction = action;
-                        break;
-                    }
-                }
-                if (viableAction != null) {
-                    break;
-                }
-            }
-
-            if (viableAction != null) {
-                Notification.Builder rebuilder = Notification.Builder.recoverBuilder(mContext, n);
-                rebuilder.setActions(viableAction);
-                rebuilder.build(); // will rewrite n
-            }
-        }
-    }
-
-    public void startPendingIntentDismissingKeyguard(final PendingIntent intent) {
-        if (!isDeviceProvisioned()) return;
-
-        final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
-        final boolean afterKeyguardGone = intent.isActivity()
-                && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
-                mCurrentUserId);
-        dismissKeyguardThenExecute(new OnDismissAction() {
-            public boolean onDismiss() {
-                new Thread() {
-                    @Override
-                    public void run() {
-                        try {
-                            // The intent we are sending is for the application, which
-                            // won't have permission to immediately start an activity after
-                            // the user switches to home.  We know it is safe to do at this
-                            // point, so make sure new activity switches are now allowed.
-                            ActivityManager.getService().resumeAppSwitches();
-                        } catch (RemoteException e) {
-                        }
-                        try {
-                            intent.send(null, 0, null, null, null, null, getActivityOptions());
-                        } catch (PendingIntent.CanceledException e) {
-                            // the stack trace isn't very helpful here.
-                            // Just log the exception message.
-                            Log.w(TAG, "Sending intent failed: " + e);
-
-                            // TODO: Dismiss Keyguard.
-                        }
-                        if (intent.isActivity()) {
-                            mAssistManager.hideAssist();
-                        }
-                    }
-                }.start();
-
-                // close the shade if it was open
-                animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
-                        true /* force */, true /* delayed */);
-                visibilityChanged(false);
-
-                return true;
-            }
-        }, afterKeyguardGone);
-    }
-
-    public void addPostCollapseAction(Runnable r) {
-    }
-
-    public boolean isCollapsing() {
-        return false;
-    }
-
-    public void wakeUpIfDozing(long time, PointF where) {
-    }
-
-    private final class NotificationClicker implements View.OnClickListener {
-        private final int[] mTmpInt2 = new int[2];
-
-        public void onClick(final View v) {
-            if (!(v instanceof ExpandableNotificationRow)) {
-                Log.e(TAG, "NotificationClicker called on a view that is not a notification row.");
-                return;
-            }
-
-            v.getLocationInWindow(mTmpInt2);
-            wakeUpIfDozing(SystemClock.uptimeMillis(),
-                    new PointF(mTmpInt2[0] + v.getWidth() / 2, mTmpInt2[1] + v.getHeight() / 2));
-
-            final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
-            final StatusBarNotification sbn = row.getStatusBarNotification();
-            if (sbn == null) {
-                Log.e(TAG, "NotificationClicker called on an unclickable notification,");
-                return;
-            }
-
-            // Check if the notification is displaying the gear, if so slide notification back
-            if (row.getSettingsRow() != null && row.getSettingsRow().isVisible()) {
-                row.animateTranslateNotification(0);
-                return;
-            }
-
-            Notification notification = sbn.getNotification();
-            final PendingIntent intent = notification.contentIntent != null
-                    ? notification.contentIntent
-                    : notification.fullScreenIntent;
-            final String notificationKey = sbn.getKey();
-
-            // Mark notification for one frame.
-            row.setJustClicked(true);
-            DejankUtils.postAfterTraversal(new Runnable() {
-                @Override
-                public void run() {
-                    row.setJustClicked(false);
-                }
-            });
-
-            final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
-            final boolean afterKeyguardGone = intent.isActivity()
-                    && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
-                            mCurrentUserId);
-            dismissKeyguardThenExecute(new OnDismissAction() {
-                public boolean onDismiss() {
-                    if (mHeadsUpManager != null && mHeadsUpManager.isHeadsUp(notificationKey)) {
-                        // Release the HUN notification to the shade.
-
-                        if (isPanelFullyCollapsed()) {
-                            HeadsUpManager.setIsClickedNotification(row, true);
-                        }
-                        //
-                        // In most cases, when FLAG_AUTO_CANCEL is set, the notification will
-                        // become canceled shortly by NoMan, but we can't assume that.
-                        mHeadsUpManager.releaseImmediately(notificationKey);
-                    }
-                    StatusBarNotification parentToCancel = null;
-                    if (shouldAutoCancel(sbn) && mGroupManager.isOnlyChildInGroup(sbn)) {
-                        StatusBarNotification summarySbn = mGroupManager.getLogicalGroupSummary(sbn)
-                                        .getStatusBarNotification();
-                        if (shouldAutoCancel(summarySbn)) {
-                            parentToCancel = summarySbn;
-                        }
-                    }
-                    final StatusBarNotification parentToCancelFinal = parentToCancel;
-                    new Thread() {
-                        @Override
-                        public void run() {
-                            try {
-                                // The intent we are sending is for the application, which
-                                // won't have permission to immediately start an activity after
-                                // the user switches to home.  We know it is safe to do at this
-                                // point, so make sure new activity switches are now allowed.
-                                ActivityManager.getService().resumeAppSwitches();
-                            } catch (RemoteException e) {
-                            }
-                            if (intent != null) {
-                                // If we are launching a work activity and require to launch
-                                // separate work challenge, we defer the activity action and cancel
-                                // notification until work challenge is unlocked.
-                                if (intent.isActivity()) {
-                                    final int userId = intent.getCreatorUserHandle()
-                                            .getIdentifier();
-                                    if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
-                                            && mKeyguardManager.isDeviceLocked(userId)) {
-                                        boolean canBypass = false;
-                                        try {
-                                            canBypass = ActivityManager.getService()
-                                                    .canBypassWorkChallenge(intent);
-                                        } catch (RemoteException e) {
-                                        }
-                                        // For direct-boot aware activities, they can be shown when
-                                        // the device is still locked without triggering the work
-                                        // challenge.
-                                        if ((!canBypass) && startWorkChallengeIfNecessary(userId,
-                                                    intent.getIntentSender(), notificationKey)) {
-                                            // Show work challenge, do not run PendingIntent and
-                                            // remove notification
-                                            return;
-                                        }
-                                    }
-                                }
-                                try {
-                                    intent.send(null, 0, null, null, null, null,
-                                            getActivityOptions());
-                                } catch (PendingIntent.CanceledException e) {
-                                    // the stack trace isn't very helpful here.
-                                    // Just log the exception message.
-                                    Log.w(TAG, "Sending contentIntent failed: " + e);
-
-                                    // TODO: Dismiss Keyguard.
-                                }
-                                if (intent.isActivity()) {
-                                    mAssistManager.hideAssist();
-                                }
-                            }
-
-                            try {
-                                mBarService.onNotificationClick(notificationKey);
-                            } catch (RemoteException ex) {
-                                // system process is dead if we're here.
-                            }
-                            if (parentToCancelFinal != null) {
-                                // We have to post it to the UI thread for synchronization
-                                mHandler.post(new Runnable() {
-                                    @Override
-                                    public void run() {
-                                        Runnable removeRunnable = new Runnable() {
-                                            @Override
-                                            public void run() {
-                                                performRemoveNotification(parentToCancelFinal);
-                                            }
-                                        };
-                                        if (isCollapsing()) {
-                                            // To avoid lags we're only performing the remove
-                                            // after the shade was collapsed
-                                            addPostCollapseAction(removeRunnable);
-                                        } else {
-                                            removeRunnable.run();
-                                        }
-                                    }
-                                });
-                            }
-                        }
-                    }.start();
-
-                    // close the shade if it was open
-                    animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
-                            true /* force */, true /* delayed */);
-                    visibilityChanged(false);
-
-                    return true;
-                }
-            }, afterKeyguardGone);
-        }
-
-        private boolean shouldAutoCancel(StatusBarNotification sbn) {
-            int flags = sbn.getNotification().flags;
-            if ((flags & Notification.FLAG_AUTO_CANCEL) != Notification.FLAG_AUTO_CANCEL) {
-                return false;
-            }
-            if ((flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
-                return false;
-            }
-            return true;
-        }
-
-        public void register(ExpandableNotificationRow row, StatusBarNotification sbn) {
-            Notification notification = sbn.getNotification();
-            if (notification.contentIntent != null || notification.fullScreenIntent != null) {
-                row.setOnClickListener(this);
-            } else {
-                row.setOnClickListener(null);
-            }
-        }
-    }
-
-    public void animateCollapsePanels(int flags, boolean force) {
-    }
-
-    public void animateCollapsePanels(int flags, boolean force, boolean delayed) {
-    }
-
-    protected boolean startWorkChallengeIfNecessary(int userId, IntentSender intendSender,
-            String notificationKey) {
-        final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null,
-                null, userId);
-        if (newIntent == null) {
-            return false;
-        }
-        final Intent callBackIntent = new Intent(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION);
-        callBackIntent.putExtra(Intent.EXTRA_INTENT, intendSender);
-        callBackIntent.putExtra(Intent.EXTRA_INDEX, notificationKey);
-        callBackIntent.setPackage(mContext.getPackageName());
-
-        PendingIntent callBackPendingIntent = PendingIntent.getBroadcast(
-                mContext,
-                0,
-                callBackIntent,
-                PendingIntent.FLAG_CANCEL_CURRENT |
-                        PendingIntent.FLAG_ONE_SHOT |
-                        PendingIntent.FLAG_IMMUTABLE);
-        newIntent.putExtra(
-                Intent.EXTRA_INTENT,
-                callBackPendingIntent.getIntentSender());
-        try {
-            ActivityManager.getService().startConfirmDeviceCredentialIntent(newIntent);
-        } catch (RemoteException ex) {
-            // ignore
-        }
-        return true;
-    }
-
-    protected Bundle getActivityOptions() {
-        // Anything launched from the notification shade should always go into the
-        // fullscreen stack.
-        ActivityOptions options = ActivityOptions.makeBasic();
-        options.setLaunchStackId(StackId.FULLSCREEN_WORKSPACE_STACK_ID);
-        return options.toBundle();
-    }
-
-    protected void visibilityChanged(boolean visible) {
-        if (mVisible != visible) {
-            mVisible = visible;
-            if (!visible) {
-                dismissPopups();
-            }
-        }
-        updateVisibleToUser();
-    }
-
-    protected void updateVisibleToUser() {
-        boolean oldVisibleToUser = mVisibleToUser;
-        mVisibleToUser = mVisible && mDeviceInteractive;
-
-        if (oldVisibleToUser != mVisibleToUser) {
-            handleVisibleToUserChanged(mVisibleToUser);
-        }
-    }
-
-    /**
-     * The LEDs are turned off when the notification panel is shown, even just a little bit.
-     * See also PhoneStatusBar.setPanelExpanded for another place where we attempt to do this.
-     */
-    protected void handleVisibleToUserChanged(boolean visibleToUser) {
-        try {
-            if (visibleToUser) {
-                boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp();
-                boolean clearNotificationEffects =
-                        !isPanelFullyCollapsed() &&
-                        (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED);
-                int notificationLoad = mNotificationData.getActiveNotifications().size();
-                if (pinnedHeadsUp && isPanelFullyCollapsed())  {
-                    notificationLoad = 1;
-                } else {
-                    MetricsLogger.histogram(mContext, "note_load", notificationLoad);
-                }
-                mBarService.onPanelRevealed(clearNotificationEffects, notificationLoad);
-            } else {
-                mBarService.onPanelHidden();
-            }
-        } catch (RemoteException ex) {
-            // Won't fail unless the world has ended.
-        }
-    }
-
-    /**
-     * Clear Buzz/Beep/Blink.
-     */
-    public void clearNotificationEffects() {
-        try {
-            mBarService.clearNotificationEffects();
-        } catch (RemoteException e) {
-            // Won't fail unless the world has ended.
-        }
-    }
-
-    public abstract boolean isPanelFullyCollapsed();
-
-    /**
-     * Cancel this notification and tell the StatusBarManagerService / NotificationManagerService
-     * about the failure.
-     *
-     * WARNING: this will call back into us.  Don't hold any locks.
-     */
-    void handleNotificationError(StatusBarNotification n, String message) {
-        removeNotification(n.getKey(), null);
-        try {
-            mBarService.onNotificationError(n.getPackageName(), n.getTag(), n.getId(), n.getUid(),
-                    n.getInitialPid(), message, n.getUserId());
-        } catch (RemoteException ex) {
-            // The end is nigh.
-        }
-    }
-
-    protected StatusBarNotification removeNotificationViews(String key, RankingMap ranking) {
-        NotificationData.Entry entry = mNotificationData.remove(key, ranking);
-        if (entry == null) {
-            Log.w(TAG, "removeNotification for unknown key: " + key);
-            return null;
-        }
-        updateNotifications();
-        return entry.notification;
-    }
-
-    protected NotificationData.Entry createNotificationViews(StatusBarNotification sbn) {
-        if (DEBUG) {
-            Log.d(TAG, "createNotificationViews(notification=" + sbn);
-        }
-        NotificationData.Entry entry = new NotificationData.Entry(sbn);
-        try {
-            entry.createIcons(mContext, sbn);
-        } catch (NotificationData.IconException exception) {
-            handleNotificationError(sbn, exception.getMessage());
-        }
-
-        // Construct the expanded view.
-        if (!inflateViews(entry, mStackScroller)) {
-            handleNotificationError(sbn, "Couldn't expand RemoteViews for: " + sbn);
-            return null;
-        }
-        return entry;
-    }
-
-    protected void addNotificationViews(Entry entry, RankingMap ranking) {
-        if (entry == null) {
-            return;
-        }
-        // Add the expanded view and icon.
-        mNotificationData.add(entry, ranking);
-        updateNotifications();
-    }
-
-    /**
-     * @param recompute wheter the number should be recomputed
-     * @return The number of notifications we show on Keyguard.
-     */
-    protected abstract int getMaxKeyguardNotifications(boolean recompute);
-
-    /**
-     * Updates expanded, dimmed and locked states of notification rows.
-     */
-    protected void updateRowStates() {
-        final int N = mStackScroller.getChildCount();
-
-        int visibleNotifications = 0;
-        boolean onKeyguard = mState == StatusBarState.KEYGUARD;
-        int maxNotifications = -1;
-        if (onKeyguard) {
-            maxNotifications = getMaxKeyguardNotifications(true /* recompute */);
-        }
-        mStackScroller.setMaxDisplayedNotifications(maxNotifications);
-        Stack<ExpandableNotificationRow> stack = new Stack<>();
-        for (int i = N - 1; i >= 0; i--) {
-            View child = mStackScroller.getChildAt(i);
-            if (!(child instanceof ExpandableNotificationRow)) {
-                continue;
-            }
-            stack.push((ExpandableNotificationRow) child);
-        }
-        while(!stack.isEmpty()) {
-            ExpandableNotificationRow row = stack.pop();
-            NotificationData.Entry entry = row.getEntry();
-            boolean childNotification = mGroupManager.isChildInGroupWithSummary(entry.notification);
-            if (onKeyguard) {
-                row.setOnKeyguard(true);
-            } else {
-                row.setOnKeyguard(false);
-                row.setSystemExpanded(visibleNotifications == 0 && !childNotification);
-            }
-            entry.row.setShowAmbient(isDozing());
-            int userId = entry.notification.getUserId();
-            boolean suppressedSummary = mGroupManager.isSummaryOfSuppressedGroup(
-                    entry.notification) && !entry.row.isRemoved();
-            boolean showOnKeyguard = shouldShowOnKeyguard(entry.notification);
-            if (suppressedSummary
-                    || (isLockscreenPublicMode(userId) && !mShowLockscreenNotifications)
-                    || (onKeyguard && !showOnKeyguard)) {
-                entry.row.setVisibility(View.GONE);
-            } else {
-                boolean wasGone = entry.row.getVisibility() == View.GONE;
-                if (wasGone) {
-                    entry.row.setVisibility(View.VISIBLE);
-                }
-                if (!childNotification && !entry.row.isRemoved()) {
-                    if (wasGone) {
-                        // notify the scroller of a child addition
-                        mStackScroller.generateAddAnimation(entry.row,
-                                !showOnKeyguard /* fromMoreCard */);
-                    }
-                    visibleNotifications++;
-                }
-            }
-            if (row.isSummaryWithChildren()) {
-                List<ExpandableNotificationRow> notificationChildren =
-                        row.getNotificationChildren();
-                int size = notificationChildren.size();
-                for (int i = size - 1; i >= 0; i--) {
-                    stack.push(notificationChildren.get(i));
-                }
-            }
-        }
-
-        mStackScroller.changeViewPosition(mDismissView, mStackScroller.getChildCount() - 1);
-        mStackScroller.changeViewPosition(mEmptyShadeView, mStackScroller.getChildCount() - 2);
-        mStackScroller.changeViewPosition(mNotificationShelf, mStackScroller.getChildCount() - 3);
-    }
-
-    public boolean isDozing() {
-        return false;
-    }
-
-    public boolean shouldShowOnKeyguard(StatusBarNotification sbn) {
-        return mShowLockscreenNotifications && !mNotificationData.isAmbient(sbn.getKey());
-    }
-
-    protected void setZenMode(int mode) {
-        if (!isDeviceProvisioned()) return;
-        mZenMode = mode;
-        updateNotifications();
-    }
-
-    // extended in PhoneStatusBar
-    protected void setShowLockscreenNotifications(boolean show) {
-        mShowLockscreenNotifications = show;
-    }
-
-    protected void setLockScreenAllowRemoteInput(boolean allowLockscreenRemoteInput) {
-        mAllowLockscreenRemoteInput = allowLockscreenRemoteInput;
-    }
-
-    private void updateLockscreenNotificationSetting() {
-        final boolean show = Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
-                1,
-                mCurrentUserId) != 0;
-        final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures(
-                null /* admin */, mCurrentUserId);
-        final boolean allowedByDpm = (dpmFlags
-                & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) == 0;
-
-        setShowLockscreenNotifications(show && allowedByDpm);
-
-        if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
-            final boolean remoteInput = Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                    Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT,
-                    0,
-                    mCurrentUserId) != 0;
-            final boolean remoteInputDpm =
-                    (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT) == 0;
-
-            setLockScreenAllowRemoteInput(remoteInput && remoteInputDpm);
-        } else {
-            setLockScreenAllowRemoteInput(false);
-        }
-    }
-
-    protected abstract void setAreThereNotifications();
-    protected abstract void updateNotifications();
-
-    public abstract void addNotification(StatusBarNotification notification,
-            RankingMap ranking, Entry oldEntry);
-    protected abstract void updateNotificationRanking(RankingMap ranking);
-    public abstract void removeNotification(String key, RankingMap ranking);
-
-    public void updateNotification(StatusBarNotification notification, RankingMap ranking) {
-        if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
-
-        final String key = notification.getKey();
-        Entry entry = mNotificationData.get(key);
-        if (entry == null) {
-            return;
-        } else {
-            mHeadsUpEntriesToRemoveOnSwitch.remove(entry);
-            mRemoteInputEntriesToRemoveOnCollapse.remove(entry);
-        }
-
-        Notification n = notification.getNotification();
-        mNotificationData.updateRanking(ranking);
-
-        boolean applyInPlace;
-        try {
-            applyInPlace = entry.cacheContentViews(mContext, notification.getNotification(),
-                    mNotificationData.isAmbient(key));
-        } catch (RuntimeException e) {
-            Log.e(TAG, "Unable to get notification remote views", e);
-            applyInPlace = false;
-        }
-        boolean shouldPeek = shouldPeek(entry, notification);
-        boolean alertAgain = alertAgain(entry, n);
-        if (DEBUG) {
-            Log.d(TAG, "applyInPlace=" + applyInPlace
-                    + " shouldPeek=" + shouldPeek
-                    + " alertAgain=" + alertAgain);
-        }
-
-        final StatusBarNotification oldNotification = entry.notification;
-        entry.notification = notification;
-        mGroupManager.onEntryUpdated(entry, oldNotification);
-
-        boolean updateSuccessful = false;
-        try {
-            if (applyInPlace) {
-                if (DEBUG) Log.d(TAG, "reusing notification for key: " + key);
-                try {
-                    entry.updateIcons(mContext, n);
-                    updateNotificationViews(entry, notification);
-                    updateSuccessful = true;
-                } catch (RuntimeException e) {
-                    // It failed to apply cleanly.
-                    Log.w(TAG, "Couldn't reapply views for package " +
-                            notification.getPackageName(), e);
-                }
-            }
-            if (!updateSuccessful) {
-                entry.updateIcons(mContext, n);
-                if (!inflateViews(entry, mStackScroller)) {
-                    handleNotificationError(notification, "Couldn't update remote views for: "
-                            + notification);
-                }
-            }
-        } catch (NotificationData.IconException e) {
-            handleNotificationError(notification, e.getMessage());
-        }
-        updateHeadsUp(key, entry, shouldPeek, alertAgain);
-        updateNotifications();
-
-        if (!notification.isClearable()) {
-            // The user may have performed a dismiss action on the notification, since it's
-            // not clearable we should snap it back.
-            mStackScroller.snapViewIfNeeded(entry.row);
-        }
-
-        if (DEBUG) {
-            // Is this for you?
-            boolean isForCurrentUser = isNotificationForCurrentProfiles(notification);
-            Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
-        }
-
-        setAreThereNotifications();
-    }
-
-    protected abstract void updateHeadsUp(String key, Entry entry, boolean shouldPeek,
-            boolean alertAgain);
-
-    private void updateNotificationViews(Entry entry, StatusBarNotification sbn) {
-        final RemoteViews contentView = entry.cachedContentView;
-        final RemoteViews bigContentView = entry.cachedBigContentView;
-        final RemoteViews headsUpContentView = entry.cachedHeadsUpContentView;
-        final RemoteViews publicContentView = entry.cachedPublicContentView;
-
-        // Reapply the RemoteViews
-        contentView.reapply(mContext, entry.getContentView(), mOnClickHandler);
-        if (bigContentView != null && entry.getExpandedContentView() != null) {
-            bigContentView.reapply(sbn.getPackageContext(mContext),
-                    entry.getExpandedContentView(),
-                    mOnClickHandler);
-        }
-        View headsUpChild = entry.getHeadsUpContentView();
-        if (headsUpContentView != null && headsUpChild != null) {
-            headsUpContentView.reapply(sbn.getPackageContext(mContext),
-                    headsUpChild, mOnClickHandler);
-        }
-        if (publicContentView != null && entry.getPublicContentView() != null) {
-            publicContentView.reapply(sbn.getPackageContext(mContext),
-                    entry.getPublicContentView(), mOnClickHandler);
-        }
-        // update the contentIntent
-        mNotificationClicker.register(entry.row, sbn);
-
-        entry.row.onNotificationUpdated(entry);
-        entry.row.resetHeight();
-    }
-
-    protected void updatePublicContentView(Entry entry,
-            StatusBarNotification sbn) {
-        final RemoteViews publicContentView = entry.cachedPublicContentView;
-        View inflatedView = entry.getPublicContentView();
-        if (entry.autoRedacted && publicContentView != null && inflatedView != null) {
-            final boolean disabledByPolicy =
-                    !adminAllowsUnredactedNotifications(entry.notification.getUserId());
-            String notificationHiddenText = mContext.getString(disabledByPolicy
-                    ? com.android.internal.R.string.notification_hidden_by_policy_text
-                    : com.android.internal.R.string.notification_hidden_text);
-            TextView titleView = (TextView) inflatedView.findViewById(android.R.id.title);
-            if (titleView != null
-                    && !titleView.getText().toString().equals(notificationHiddenText)) {
-                publicContentView.setTextViewText(android.R.id.title, notificationHiddenText);
-                publicContentView.reapply(sbn.getPackageContext(mContext),
-                        inflatedView, mOnClickHandler);
-                entry.row.onNotificationUpdated(entry);
-            }
-        }
-    }
-
-    protected void notifyHeadsUpScreenOff() {
-        maybeEscalateHeadsUp();
-    }
-
-    private boolean alertAgain(Entry oldEntry, Notification newNotification) {
-        return oldEntry == null || !oldEntry.hasInterrupted()
-                || (newNotification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0;
-    }
-
-    protected boolean shouldPeek(Entry entry) {
-        return shouldPeek(entry, entry.notification);
-    }
-
-    protected boolean shouldPeek(Entry entry, StatusBarNotification sbn) {
-        if (!mUseHeadsUp || isDeviceInVrMode()) {
-            return false;
-        }
-
-        if (mNotificationData.shouldFilterOut(sbn)) {
-            if (DEBUG) Log.d(TAG, "No peeking: filtered notification: " + sbn.getKey());
-            return false;
-        }
-
-        boolean inUse = mPowerManager.isScreenOn();
-        try {
-            inUse = inUse && !mDreamManager.isDreaming();
-        } catch (RemoteException e) {
-            Log.d(TAG, "failed to query dream manager", e);
-        }
-
-        if (!inUse && !isDozing()) {
-            if (DEBUG) {
-                Log.d(TAG, "No peeking: not in use: " + sbn.getKey());
-            }
-            return false;
-        }
-
-        if (mNotificationData.shouldSuppressScreenOn(sbn.getKey())) {
-            if (DEBUG) Log.d(TAG, "No peeking: suppressed by DND: " + sbn.getKey());
-            return false;
-        }
-
-        if (entry.hasJustLaunchedFullScreenIntent()) {
-            if (DEBUG) Log.d(TAG, "No peeking: recent fullscreen: " + sbn.getKey());
-            return false;
-        }
-
-        if (isSnoozedPackage(sbn)) {
-            if (DEBUG) Log.d(TAG, "No peeking: snoozed package: " + sbn.getKey());
-            return false;
-        }
-
-        if (mNotificationData.getImportance(sbn.getKey()) < NotificationManager.IMPORTANCE_HIGH) {
-            if (DEBUG) Log.d(TAG, "No peeking: unimportant notification: " + sbn.getKey());
-            return false;
-        }
-
-        if (sbn.getNotification().fullScreenIntent != null) {
-            if (mAccessibilityManager.isTouchExplorationEnabled()) {
-                if (DEBUG) Log.d(TAG, "No peeking: accessible fullscreen: " + sbn.getKey());
-                return false;
-            } else {
-                // we only allow head-up on the lockscreen if it doesn't have a fullscreen intent
-                return !mStatusBarKeyguardViewManager.isShowing()
-                        || mStatusBarKeyguardViewManager.isOccluded();
-            }
-        }
-
-        return true;
-    }
-
-    protected abstract boolean isSnoozedPackage(StatusBarNotification sbn);
-
-    public void setInteracting(int barWindow, boolean interacting) {
-        // hook for subclasses
-    }
-
-    public void setBouncerShowing(boolean bouncerShowing) {
-        mBouncerShowing = bouncerShowing;
-    }
-
-    /**
-     * @return Whether the security bouncer from Keyguard is showing.
-     */
-    public boolean isBouncerShowing() {
-        return mBouncerShowing;
-    }
-
-    public void destroy() {
-        mContext.unregisterReceiver(mBroadcastReceiver);
-        try {
-            mNotificationListener.unregisterAsSystemService();
-        } catch (RemoteException e) {
-            // Ignore.
-        }
-        mDeviceProvisionedController.removeCallback(mDeviceProvisionedListener);
-    }
-
-    /**
-     * @return a PackageManger for userId or if userId is < 0 (USER_ALL etc) then
-     *         return PackageManager for mContext
-     */
-    public static PackageManager getPackageManagerForUser(Context context, int userId) {
-        Context contextForUser = context;
-        // UserHandle defines special userId as negative values, e.g. USER_ALL
-        if (userId >= 0) {
-            try {
-                // Create a context for the correct user so if a package isn't installed
-                // for user 0 we can still load information about the package.
-                contextForUser =
-                        context.createPackageContextAsUser(context.getPackageName(),
-                        Context.CONTEXT_RESTRICTED,
-                        new UserHandle(userId));
-            } catch (NameNotFoundException e) {
-                // Shouldn't fail to find the package name for system ui.
-            }
-        }
-        return contextForUser.getPackageManager();
-    }
-
-    @Override
-    public void logNotificationExpansion(String key, boolean userAction, boolean expanded) {
-        try {
-            mBarService.onNotificationExpansionChanged(key, userAction, expanded);
-        } catch (RemoteException e) {
-            // Ignore.
-        }
-    }
-
-    public boolean isKeyguardSecure() {
-        if (mStatusBarKeyguardViewManager == null) {
-            // startKeyguard() hasn't been called yet, so we don't know.
-            // Make sure anything that needs to know isKeyguardSecure() checks and re-checks this
-            // value onVisibilityChanged().
-            Slog.w(TAG, "isKeyguardSecure() called before startKeyguard(), returning false",
-                    new Throwable());
-            return false;
-        }
-        return mStatusBarKeyguardViewManager.isSecure();
-    }
-
-    @Override
-    public void showAssistDisclosure() {
-        if (mAssistManager != null) {
-            mAssistManager.showDisclosure();
-        }
-    }
-
-    @Override
-    public void startAssist(Bundle args) {
-        if (mAssistManager != null) {
-            mAssistManager.startAssist(args);
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 013554c..d1245b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -51,10 +51,12 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.MenuItem;
 import com.android.systemui.statusbar.notification.HybridNotificationView;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.stack.AnimationProperties;
 import com.android.systemui.statusbar.stack.ExpandableViewState;
@@ -120,7 +122,7 @@
     private int mNotificationColor;
     private ExpansionLogger mLogger;
     private String mLoggingKey;
-    private NotificationSettingsIconRow mSettingsIconRow;
+    private NotificationMenuRow mMenuRow;
     private NotificationGuts mGuts;
     private NotificationData.Entry mEntry;
     private StatusBarNotification mStatusBarNotification;
@@ -132,7 +134,7 @@
     private boolean mChildrenExpanded;
     private boolean mIsSummaryWithChildren;
     private NotificationChildrenContainer mChildrenContainer;
-    private ViewStub mSettingsIconRowStub;
+    private ViewStub mMenuRowStub;
     private ViewStub mGutsStub;
     private boolean mIsSystemChildExpanded;
     private boolean mIsPinned;
@@ -204,7 +206,9 @@
     private boolean mIsLastChild;
     private Runnable mOnDismissRunnable;
     private boolean mIsLowPriority;
+    private boolean mIsColorized;
 
+    @Override
     public boolean isGroupExpansionChanging() {
         if (isChildInGroup()) {
             return mNotificationParent.isGroupExpansionChanging();
@@ -295,6 +299,7 @@
         for (NotificationContentView l : mLayouts) {
             l.onNotificationUpdated(entry);
         }
+        mIsColorized = mStatusBarNotification.getNotification().isColorized();
         mShowingPublicInitialized = false;
         updateNotificationColor();
         if (mIsSummaryWithChildren) {
@@ -386,8 +391,8 @@
 
     public void setAppName(String appName) {
         mAppName = appName;
-        if (mSettingsIconRow != null) {
-            mSettingsIconRow.setAppName(mAppName);
+        if (mMenuRow != null) {
+            mMenuRow.setAppName(mAppName);
         }
     }
 
@@ -418,6 +423,7 @@
         row.setIsChildInGroup(false, null);
     }
 
+    @Override
     public boolean isChildInGroup() {
         return mNotificationParent != null;
     }
@@ -431,7 +437,7 @@
      * @param parent the new parent notification
      */
     public void setIsChildInGroup(boolean isChildInGroup, ExpandableNotificationRow parent) {;
-        boolean childInGroup = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS && isChildInGroup;
+        boolean childInGroup = StatusBar.ENABLE_CHILD_NOTIFICATIONS && isChildInGroup;
         mNotificationParent = childInGroup ? parent : null;
         mPrivateLayout.setIsChildInGroup(childInGroup);
         resetBackgroundAlpha();
@@ -455,7 +461,7 @@
 
     @Override
     protected boolean handleSlideBack() {
-        if (mSettingsIconRow != null && mSettingsIconRow.isVisible()) {
+        if (mMenuRow != null && mMenuRow.isVisible()) {
             animateTranslateNotification(0 /* targetLeft */);
             return true;
         }
@@ -679,6 +685,13 @@
         mHeadsUpManager = headsUpManager;
     }
 
+    public void setGutsView(MenuItem item) {
+        if (mGuts != null) {
+            item.gutsContent.setInteractionListener(mGuts);
+            mGuts.setGutsContent(item.gutsContent);
+        }
+    }
+
     public void reInflateViews() {
         initDimens();
         if (mIsSummaryWithChildren) {
@@ -695,16 +708,16 @@
             mGuts.setVisibility(oldGuts.getVisibility());
             addView(mGuts, index);
         }
-        if (mSettingsIconRow != null) {
-            View oldSettings = mSettingsIconRow;
-            int settingsIndex = indexOfChild(oldSettings);
-            removeView(oldSettings);
-            mSettingsIconRow = (NotificationSettingsIconRow) LayoutInflater.from(mContext).inflate(
-                    R.layout.notification_settings_icon_row, this, false);
-            mSettingsIconRow.setNotificationRowParent(ExpandableNotificationRow.this);
-            mSettingsIconRow.setAppName(mAppName);
-            mSettingsIconRow.setVisibility(oldSettings.getVisibility());
-            addView(mSettingsIconRow, settingsIndex);
+        if (mMenuRow != null) {
+            View oldMenu = mMenuRow;
+            int menuIndex = indexOfChild(oldMenu);
+            removeView(oldMenu);
+            mMenuRow = (NotificationMenuRow) LayoutInflater.from(mContext).inflate(
+                    R.layout.notification_menu_row, this, false);
+            mMenuRow.setNotificationRowParent(ExpandableNotificationRow.this);
+            mMenuRow.setAppName(mAppName);
+            mMenuRow.setVisibility(oldMenu.getVisibility());
+            addView(mMenuRow, menuIndex);
 
         }
         for (NotificationContentView l : mLayouts) {
@@ -1033,21 +1046,19 @@
         super.onFinishInflate();
         mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
         mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
-
         mLayouts = new NotificationContentView[] {mPrivateLayout, mPublicLayout};
 
         for (NotificationContentView l : mLayouts) {
             l.setExpandClickListener(mExpandClickListener);
             l.setContainingNotification(this);
         }
-
-        mSettingsIconRowStub = (ViewStub) findViewById(R.id.settings_icon_row_stub);
-        mSettingsIconRowStub.setOnInflateListener(new ViewStub.OnInflateListener() {
+        mMenuRowStub = (ViewStub) findViewById(R.id.menu_row_stub);
+        mMenuRowStub.setOnInflateListener(new ViewStub.OnInflateListener() {
             @Override
             public void onInflate(ViewStub stub, View inflated) {
-                mSettingsIconRow = (NotificationSettingsIconRow) inflated;
-                mSettingsIconRow.setNotificationRowParent(ExpandableNotificationRow.this);
-                mSettingsIconRow.setAppName(mAppName);
+                mMenuRow = (NotificationMenuRow) inflated;
+                mMenuRow.setNotificationRowParent(ExpandableNotificationRow.this);
+                mMenuRow.setAppName(mAppName);
             }
         });
         mGutsStub = (ViewStub) findViewById(R.id.notification_guts_stub);
@@ -1079,7 +1090,7 @@
             mTranslateableViews.add(getChildAt(i));
         }
         // Remove views that don't translate
-        mTranslateableViews.remove(mSettingsIconRowStub);
+        mTranslateableViews.remove(mMenuRowStub);
         mTranslateableViews.remove(mChildrenContainerStub);
         mTranslateableViews.remove(mGutsStub);
     }
@@ -1094,8 +1105,8 @@
             }
         }
         invalidateOutline();
-        if (mSettingsIconRow != null) {
-            mSettingsIconRow.resetState();
+        if (mMenuRow != null) {
+            mMenuRow.resetState(true /* notify */);
         }
     }
 
@@ -1122,8 +1133,8 @@
             }
         }
         invalidateOutline();
-        if (mSettingsIconRow != null) {
-            mSettingsIconRow.updateSettingsIcons(translationX, getMeasuredWidth());
+        if (mMenuRow != null) {
+            mMenuRow.updateMenuAlpha(translationX, getMeasuredWidth());
         }
     }
 
@@ -1160,8 +1171,8 @@
 
             @Override
             public void onAnimationEnd(Animator anim) {
-                if (!cancelled && mSettingsIconRow != null && leftTarget == 0) {
-                    mSettingsIconRow.resetState();
+                if (!cancelled && mMenuRow != null && leftTarget == 0) {
+                    mMenuRow.resetState(true /* notify */);
                     mTranslateAnim = null;
                 }
             }
@@ -1171,17 +1182,17 @@
     }
 
     public float getSpaceForGear() {
-        if (mSettingsIconRow != null) {
-            return mSettingsIconRow.getSpaceForGear();
+        if (mMenuRow != null) {
+            return mMenuRow.getSpaceForMenu();
         }
         return 0;
     }
 
-    public NotificationSettingsIconRow getSettingsRow() {
-        if (mSettingsIconRow == null) {
-            mSettingsIconRowStub.inflate();
+    public NotificationMenuRow getSettingsRow() {
+        if (mMenuRow == null) {
+            mMenuRowStub.inflate();
         }
-        return mSettingsIconRow;
+        return mMenuRow;
     }
 
     public void inflateGuts() {
@@ -1404,12 +1415,13 @@
         }
     }
 
+    @Override
     public boolean isGroupExpanded() {
         return mGroupManager.isGroupExpanded(mStatusBarNotification);
     }
 
     private void onChildrenCountChanged() {
-        mIsSummaryWithChildren = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS
+        mIsSummaryWithChildren = StatusBar.ENABLE_CHILD_NOTIFICATIONS
                 && mChildrenContainer != null && mChildrenContainer.getNotificationChildCount() > 0;
         if (mIsSummaryWithChildren && mChildrenContainer.getHeaderView() == null) {
             mChildrenContainer.recreateNotificationHeader(mExpandClickListener,
@@ -1457,8 +1469,8 @@
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
         updateMaxHeights();
-        if (mSettingsIconRow != null) {
-            mSettingsIconRow.updateVerticalLocation();
+        if (mMenuRow != null) {
+            mMenuRow.updateVerticalLocation();
         }
         updateContentShiftHeight();
     }
@@ -1505,6 +1517,7 @@
         mSensitiveHiddenInGeneral = hideSensitive;
     }
 
+    @Override
     public void setHideSensitiveForIntrinsicHeight(boolean hideSensitive) {
         mHideSensitiveForIntrinsicHeight = hideSensitive;
         if (mIsSummaryWithChildren) {
@@ -1517,6 +1530,7 @@
         }
     }
 
+    @Override
     public void setHideSensitive(boolean hideSensitive, boolean animated, long delay,
             long duration) {
         boolean oldShowingPublic = mShowingPublic;
@@ -1581,6 +1595,7 @@
         }
     }
 
+    @Override
     public boolean mustStayOnScreen() {
         return mIsHeadsUp;
     }
@@ -1853,10 +1868,16 @@
             } else if (isUserLocked()) {
                 return mChildrenContainer.getGroupExpandFraction();
             }
+        } else if (isColorized()) {
+            return -1.0f;
         }
         return 0.0f;
     }
 
+    private boolean isColorized() {
+        return mIsColorized;
+    }
+
     @Override
     protected boolean disallowSingleClick(MotionEvent event) {
         float x = event.getX();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 37a900e..6a1f470 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -404,7 +404,9 @@
     }
 
     /**
-     * @return an amount between 0 and 1 of increased padding that this child needs
+     * @return an amount between -1 and 1 of increased padding that this child needs. 1 means it
+     * needs a full increased padding while -1 means it needs no padding at all. For 0.0f the normal
+     * padding is applied.
      */
     public float getIncreasedPaddingAmount() {
         return 0.0f;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 4d0ce12..e0ddf13 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -89,6 +89,7 @@
     private StatusBarNotification mStatusBarNotification;
     private NotificationGroupManager mGroupManager;
     private RemoteInputController mRemoteInputController;
+    private Runnable mExpandedVisibleListener;
 
     private final ViewTreeObserver.OnPreDrawListener mEnableAnimationPredrawListener
             = new ViewTreeObserver.OnPreDrawListener() {
@@ -498,11 +499,6 @@
                         com.android.internal.R.dimen.notification_action_list_height);
         }
 
-        if (isVisibleOrTransitioning(VISIBLE_TYPE_AMBIENT)) {
-            return mContractedChild.getHeight() + mContext.getResources().getDimensionPixelSize(
-                    com.android.internal.R.dimen.notification_action_list_height);
-        }
-
         // Transition between heads-up & expanded, or pinned.
         if (mHeadsUpChild != null && mExpandedChild != null) {
             boolean transitioningBetweenHunAndExpanded =
@@ -522,7 +518,9 @@
         }
 
         int hint;
-        if (mHeadsUpChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_HEADSUP)) {
+        if (mAmbientChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_AMBIENT)) {
+            hint = mAmbientChild.getHeight();
+        } else if (mHeadsUpChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_HEADSUP)) {
             hint = mHeadsUpChild.getHeight();
         } else if (mExpandedChild != null) {
             hint = mExpandedChild.getHeight();
@@ -684,10 +682,6 @@
                     visibleView.setVisibility(VISIBLE);
                     transferRemoteInputFocus(visibleType);
                 }
-                NotificationViewWrapper visibleWrapper = getVisibleWrapper(visibleType);
-                if (visibleWrapper != null) {
-                    visibleWrapper.setContentHeight(mContentHeight, getMinContentHeightHint());
-                }
 
                 if (animate && ((visibleType == VISIBLE_TYPE_EXPANDED && mExpandedChild != null)
                         || (visibleType == VISIBLE_TYPE_HEADSUP && mHeadsUpChild != null)
@@ -701,6 +695,10 @@
                 if (changedType) {
                     focusExpandButtonIfNecessary();
                 }
+                NotificationViewWrapper visibleWrapper = getVisibleWrapper(visibleType);
+                if (visibleWrapper != null) {
+                    visibleWrapper.setContentHeight(mContentHeight, getMinContentHeightHint());
+                }
                 updateBackgroundColor(animate);
             }
         }
@@ -712,11 +710,21 @@
         forceUpdateVisibility(VISIBLE_TYPE_HEADSUP, mHeadsUpChild, mHeadsUpWrapper);
         forceUpdateVisibility(VISIBLE_TYPE_SINGLELINE, mSingleLineView, mSingleLineView);
         forceUpdateVisibility(VISIBLE_TYPE_AMBIENT, mAmbientChild, mAmbientWrapper);
+        fireExpandedVisibleListenerIfVisible();
         // forceUpdateVisibilities cancels outstanding animations without updating the
         // mAnimationStartVisibleType. Do so here instead.
         mAnimationStartVisibleType = UNDEFINED;
     }
 
+    private void fireExpandedVisibleListenerIfVisible() {
+        if (mExpandedVisibleListener != null && mExpandedChild != null && isShown()
+                && mExpandedChild.getVisibility() == VISIBLE) {
+            Runnable listener = mExpandedVisibleListener;
+            mExpandedVisibleListener = null;
+            listener.run();
+        }
+    }
+
     private void forceUpdateVisibility(int type, View view, TransformableView wrapper) {
         if (view == null) {
             return;
@@ -770,6 +778,7 @@
                 mSingleLineView, mSingleLineView);
         updateViewVisibility(visibleType, VISIBLE_TYPE_AMBIENT,
                 mAmbientChild, mAmbientWrapper);
+        fireExpandedVisibleListenerIfVisible();
         // updateViewVisibilities cancels outstanding animations without updating the
         // mAnimationStartVisibleType. Do so here instead.
         mAnimationStartVisibleType = UNDEFINED;
@@ -801,6 +810,7 @@
                 mAnimationStartVisibleType = UNDEFINED;
             }
         });
+        fireExpandedVisibleListenerIfVisible();
     }
 
     private void transferRemoteInputFocus(int visibleType) {
@@ -992,7 +1002,6 @@
         mStatusBarNotification = entry.notification;
         mBeforeN = entry.targetSdk < Build.VERSION_CODES.N;
         updateSingleLineView();
-        applyRemoteInput(entry);
         if (mContractedChild != null) {
             mContractedWrapper.notifyContentUpdated(entry.notification, mIsLowPriority);
         }
@@ -1005,6 +1014,7 @@
         if (mAmbientChild != null) {
             mAmbientWrapper.notifyContentUpdated(entry.notification, mIsLowPriority);
         }
+        applyRemoteInput(entry);
         updateShowingLegacyBackground();
         mForceSelectNextLayout = true;
         setDark(mDark, false /* animate */, 0 /* delay */);
@@ -1046,7 +1056,8 @@
         View bigContentView = mExpandedChild;
         if (bigContentView != null) {
             mExpandedRemoteInput = applyRemoteInput(bigContentView, entry, hasRemoteInput,
-                    mPreviousExpandedRemoteInputIntent, mCachedExpandedRemoteInput);
+                    mPreviousExpandedRemoteInputIntent, mCachedExpandedRemoteInput,
+                    mExpandedWrapper);
         } else {
             mExpandedRemoteInput = null;
         }
@@ -1060,7 +1071,7 @@
         View headsUpContentView = mHeadsUpChild;
         if (headsUpContentView != null) {
             mHeadsUpRemoteInput = applyRemoteInput(headsUpContentView, entry, hasRemoteInput,
-                    mPreviousHeadsUpRemoteInputIntent, mCachedHeadsUpRemoteInput);
+                    mPreviousHeadsUpRemoteInputIntent, mCachedHeadsUpRemoteInput, mHeadsUpWrapper);
         } else {
             mHeadsUpRemoteInput = null;
         }
@@ -1074,7 +1085,7 @@
 
     private RemoteInputView applyRemoteInput(View view, NotificationData.Entry entry,
             boolean hasRemoteInput, PendingIntent existingPendingIntent,
-            RemoteInputView cachedView) {
+            RemoteInputView cachedView, NotificationViewWrapper wrapper) {
         View actionContainerCandidate = view.findViewById(
                 com.android.internal.R.id.actions_container);
         if (actionContainerCandidate instanceof FrameLayout) {
@@ -1113,6 +1124,8 @@
                         mContext.getColor(R.color.remote_input_text_enabled),
                         mContext.getColor(R.color.remote_input_hint)));
 
+                existing.setWrapper(wrapper);
+
                 if (existingPendingIntent != null || existing.isActive()) {
                     // The current action could be gone, or the pending intent no longer valid.
                     // If we find a matching action in the new notification, focus, otherwise close.
@@ -1301,6 +1314,24 @@
         }
     }
 
+    @Override
+    public void onVisibilityAggregated(boolean isVisible) {
+        super.onVisibilityAggregated(isVisible);
+        if (isVisible) {
+            fireExpandedVisibleListenerIfVisible();
+        }
+    }
+
+    /**
+     * Sets a one-shot listener for when the expanded view becomes visible.
+     *
+     * This will fire the listener immediately if the expanded view is already visible.
+     */
+    public void setOnExpandedVisibleListener(Runnable r) {
+        mExpandedVisibleListener = r;
+        fireExpandedVisibleListenerIfVisible();
+    }
+
     public void setIsLowPriority(boolean isLowPriority) {
         mIsLowPriority = isLowPriority;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 8c04a1a..bbfcf31 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -25,6 +25,7 @@
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationListenerService.Ranking;
 import android.service.notification.NotificationListenerService.RankingMap;
+import android.service.notification.SnoozeCriterion;
 import android.service.notification.StatusBarNotification;
 import android.util.ArrayMap;
 import android.view.View;
@@ -34,12 +35,14 @@
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.util.NotificationColorUtil;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -71,6 +74,7 @@
         public RemoteViews cachedPublicContentView;
         public RemoteViews cachedAmbientContentView;
         public CharSequence remoteInputText;
+        public List<SnoozeCriterion> snoozeCriteria;
         private int mCachedContrastColor = COLOR_INVALID;
         private int mCachedContrastColorIsFor = COLOR_INVALID;
 
@@ -456,6 +460,14 @@
          return null;
     }
 
+    public List<SnoozeCriterion> getSnoozeCriteria(String key) {
+        if (mRankingMap != null) {
+            mRankingMap.getRanking(key, mTmpRanking);
+            return mTmpRanking.getSnoozeCriteria();
+        }
+        return null;
+    }
+
     public NotificationChannel getChannel(String key) {
         if (mRankingMap != null) {
             mRankingMap.getRanking(key, mTmpRanking);
@@ -478,6 +490,7 @@
                         mGroupManager.onEntryUpdated(entry, oldSbn);
                     }
                     entry.channel = getChannel(entry.key);
+                    entry.snoozeCriteria = getSnoozeCriteria(entry.key);
                 }
             }
         }
@@ -506,7 +519,7 @@
         Collections.sort(mSortedAndFiltered, mRankingComparator);
     }
 
-    boolean shouldFilterOut(StatusBarNotification sbn) {
+    public boolean shouldFilterOut(StatusBarNotification sbn) {
         if (!(mEnvironment.isDeviceProvisioned() ||
                 showNotificationEvenIfUnprovisioned(sbn))) {
             return true;
@@ -523,7 +536,7 @@
             return true;
         }
 
-        if (!BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS
+        if (!StatusBar.ENABLE_CHILD_NOTIFICATIONS
                 && mGroupManager.isChildInGroupWithSummary(sbn)) {
             return true;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 83104e6..f6056dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -40,6 +40,7 @@
 import android.view.ViewAnimationUtils;
 import android.view.ViewGroup;
 import android.widget.CompoundButton;
+import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.RadioButton;
@@ -53,6 +54,8 @@
 import com.android.settingslib.Utils;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.GutsContent;
 import com.android.systemui.statusbar.stack.StackStateAnimator;
 
 import java.util.Set;
@@ -60,7 +63,8 @@
 /**
  * The guts of a notification revealed when performing a long press.
  */
-public class NotificationGuts extends LinearLayout {
+public class NotificationGuts extends FrameLayout
+        implements NotificationMenuRowProvider.GutsInteractionListener {
     private static final String TAG = "NotificationGuts";
     private static final long CLOSE_GUTS_DELAY = 8000;
 
@@ -69,24 +73,14 @@
     private int mClipBottomAmount;
     private int mActualHeight;
     private boolean mExposed;
-    private INotificationManager mINotificationManager;
-    private int mStartingUserImportance;
-    private StatusBarNotification mStatusBarNotification;
-    private NotificationChannel mNotificationChannel;
-
-    private View mImportanceGroup;
-    private View mChannelDisabled;
-    private Switch mChannelEnabledSwitch;
-    private RadioButton mMinImportanceButton;
-    private RadioButton mLowImportanceButton;
-    private RadioButton mDefaultImportanceButton;
-    private RadioButton mHighImportanceButton;
 
     private Handler mHandler;
     private Runnable mFalsingCheck;
     private boolean mNeedsFalsingProtection;
     private OnGutsClosedListener mListener;
 
+    private GutsContent mGutsContent;
+
     public interface OnGutsClosedListener {
         public void onGutsClosed(NotificationGuts guts);
     }
@@ -103,11 +97,22 @@
                 }
             }
         };
-        final TypedArray ta =
-                context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Theme, 0, 0);
+        final TypedArray ta = context.obtainStyledAttributes(attrs,
+                com.android.internal.R.styleable.Theme, 0, 0);
         ta.recycle();
     }
 
+    public NotificationGuts(Context context) {
+        this(context, null);
+
+    }
+
+    public void setGutsContent(GutsContent content) {
+        mGutsContent = content;
+        removeAllViews();
+        addView(mGutsContent.getContentView());
+    }
+
     public void resetFalsingCheck() {
         mHandler.removeCallbacks(mFalsingCheck);
         if (mNeedsFalsingProtection && mExposed) {
@@ -165,213 +170,23 @@
         void onClick(View v, int appUid);
     }
 
-    void bindNotification(final PackageManager pm, final INotificationManager iNotificationManager,
-            final StatusBarNotification sbn, final NotificationChannel channel,
-            OnSettingsClickListener onSettingsClick,
-            OnClickListener onDoneClick, final Set<String> nonBlockablePkgs) {
-        mINotificationManager = iNotificationManager;
-        mNotificationChannel = channel;
-        mStatusBarNotification = sbn;
-        mStartingUserImportance = channel.getImportance();
-
-        final String pkg = sbn.getPackageName();
-        int appUid = -1;
-        String appname = pkg;
-        Drawable pkgicon = null;
-        try {
-            final ApplicationInfo info = pm.getApplicationInfo(pkg,
-                    PackageManager.MATCH_UNINSTALLED_PACKAGES
-                            | PackageManager.MATCH_DISABLED_COMPONENTS
-                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
-                            | PackageManager.MATCH_DIRECT_BOOT_AWARE);
-            if (info != null) {
-                appUid = info.uid;
-                appname = String.valueOf(pm.getApplicationLabel(info));
-                pkgicon = pm.getApplicationIcon(info);
-            }
-        } catch (PackageManager.NameNotFoundException e) {
-            // app is gone, just show package name and generic icon
-            pkgicon = pm.getDefaultActivityIcon();
-        }
-
-        // If this is the placeholder channel, don't use our channel-specific text.
-        String appNameText;
-        CharSequence channelNameText;
-        if (channel.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
-            appNameText = appname;
-            channelNameText = mContext.getString(R.string.notification_header_default_channel);
-        } else {
-            appNameText = mContext.getString(R.string.notification_importance_header_app, appname);
-            channelNameText = channel.getName();
-        }
-        ((TextView) findViewById(R.id.pkgname)).setText(appNameText);
-        ((TextView) findViewById(R.id.channel_name)).setText(channelNameText);
-
-        // Settings button.
-        final TextView settingsButton = (TextView) findViewById(R.id.more_settings);
-        if (appUid >= 0 && onSettingsClick != null) {
-            final int appUidF = appUid;
-            settingsButton.setOnClickListener(
-                    (View view) -> { onSettingsClick.onClick(view, appUidF); });
-            settingsButton.setText(R.string.notification_more_settings);
-        } else {
-            settingsButton.setVisibility(View.GONE);
-        }
-
-        // Done button.
-        final TextView doneButton = (TextView) findViewById(R.id.done);
-        doneButton.setText(R.string.notification_done);
-        doneButton.setOnClickListener(onDoneClick);
-
-        boolean nonBlockable = false;
-        try {
-            final PackageInfo info = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
-            nonBlockable = Utils.isSystemPackage(getResources(), pm, info);
-        } catch (PackageManager.NameNotFoundException e) {
-            // unlikely.
-        }
-        if (nonBlockablePkgs != null) {
-            nonBlockable |= nonBlockablePkgs.contains(pkg);
-        }
-
-        final View importanceButtons = findViewById(R.id.importance_buttons);
-        bindToggles(importanceButtons, mStartingUserImportance, nonBlockable);
-
-        // Importance Text (hardcoded to 4 importance levels)
-        final ViewGroup importanceTextGroup =
-                (ViewGroup) findViewById(R.id.importance_buttons_text);
-        final int size = importanceTextGroup.getChildCount();
-        for (int i = 0; i < size; i++) {
-            int importanceNameResId = 0;
-            int importanceDescResId = 0;
-            switch (i) {
-                case 0:
-                    importanceNameResId = R.string.high_importance;
-                    importanceDescResId = R.string.notification_importance_high;
-                    break;
-                case 1:
-                    importanceNameResId = R.string.default_importance;
-                    importanceDescResId = R.string.notification_importance_default;
-                    break;
-                case 2:
-                    importanceNameResId = R.string.low_importance;
-                    importanceDescResId = R.string.notification_importance_low;
-                    break;
-                case 3:
-                    importanceNameResId = R.string.min_importance;
-                    importanceDescResId = R.string.notification_importance_min;
-                    break;
-                default:
-                    Log.e(TAG, "Too many importance groups in this layout.");
-                    break;
-            }
-            final ViewGroup importanceChildGroup = (ViewGroup) importanceTextGroup.getChildAt(i);
-            ((TextView) importanceChildGroup.getChildAt(0)).setText(importanceNameResId);
-            ((TextView) importanceChildGroup.getChildAt(1)).setText(importanceDescResId);
-        }
-
-        // Top-level importance group
-        mImportanceGroup = findViewById(R.id.importance);
-        mChannelDisabled = findViewById(R.id.channel_disabled);
-        updateImportanceGroup();
-    }
-
-    public boolean hasImportanceChanged() {
-        return mStartingUserImportance != getSelectedImportance();
-    }
-
-    private void saveImportance() {
-        int selectedImportance = getSelectedImportance();
-        if (selectedImportance == mStartingUserImportance) {
-            return;
-        }
-        MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
-                selectedImportance - mStartingUserImportance);
-        mNotificationChannel.setImportance(selectedImportance);
-        try {
-            mINotificationManager.updateNotificationChannelForPackage(
-                    mStatusBarNotification.getPackageName(), mStatusBarNotification.getUid(),
-                    mNotificationChannel);
-        } catch (RemoteException e) {
-            // :(
-        }
-    }
-
-    private int getSelectedImportance() {
-        if (!mChannelEnabledSwitch.isChecked()) {
-            return NotificationManager.IMPORTANCE_NONE;
-        } else if (mMinImportanceButton.isChecked()) {
-            return NotificationManager.IMPORTANCE_MIN;
-        } else if (mLowImportanceButton.isChecked()) {
-            return NotificationManager.IMPORTANCE_LOW;
-        } else if (mDefaultImportanceButton.isChecked()) {
-            return NotificationManager.IMPORTANCE_DEFAULT;
-        } else if (mHighImportanceButton.isChecked()) {
-            return NotificationManager.IMPORTANCE_HIGH;
-        } else {
-            return NotificationManager.IMPORTANCE_UNSPECIFIED;
-        }
-    }
-
-    private void bindToggles(final View importanceButtons, final int importance,
-            final boolean nonBlockable) {
-        // Enabled Switch
-        mChannelEnabledSwitch = (Switch) findViewById(R.id.channel_enabled_switch);
-        mChannelEnabledSwitch.setChecked(importance != NotificationManager.IMPORTANCE_NONE);
-        mChannelEnabledSwitch.setVisibility(nonBlockable ? View.INVISIBLE : View.VISIBLE);
-
-        // Importance Buttons
-        mMinImportanceButton = (RadioButton) importanceButtons.findViewById(R.id.min_importance);
-        mLowImportanceButton = (RadioButton) importanceButtons.findViewById(R.id.low_importance);
-        mDefaultImportanceButton =
-                (RadioButton) importanceButtons.findViewById(R.id.default_importance);
-        mHighImportanceButton = (RadioButton) importanceButtons.findViewById(R.id.high_importance);
-
-        // Set to current importance setting
-        switch (importance) {
-            case NotificationManager.IMPORTANCE_UNSPECIFIED:
-            case NotificationManager.IMPORTANCE_NONE:
-                break;
-            case NotificationManager.IMPORTANCE_MIN:
-                mMinImportanceButton.setChecked(true);
-                break;
-            case NotificationManager.IMPORTANCE_LOW:
-                mLowImportanceButton.setChecked(true);
-                break;
-            case NotificationManager.IMPORTANCE_DEFAULT:
-                mDefaultImportanceButton.setChecked(true);
-                break;
-            case NotificationManager.IMPORTANCE_HIGH:
-            case NotificationManager.IMPORTANCE_MAX:
-                mHighImportanceButton.setChecked(true);
-                break;
-        }
-
-        // Callback when checked.
-        mChannelEnabledSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
-            resetFalsingCheck();
-            updateImportanceGroup();
-        });
-        ((RadioGroup) importanceButtons).setOnCheckedChangeListener(
-                (buttonView, isChecked) -> { resetFalsingCheck(); });
-    }
-
-    private void updateImportanceGroup() {
-        final boolean disabled = getSelectedImportance() == NotificationManager.IMPORTANCE_NONE;
-        mImportanceGroup.setVisibility(disabled ? View.GONE : View.VISIBLE);
-        mChannelDisabled.setVisibility(disabled ? View.VISIBLE : View.GONE);
-    }
-
     public void closeControls(int x, int y, boolean saveImportance) {
-        if (saveImportance) {
-            saveImportance();
-        }
         if (getWindowToken() == null) {
             if (mListener != null) {
                 mListener.onGutsClosed(this);
             }
             return;
         }
+        if (mGutsContent == null || !mGutsContent.handleCloseControls()) {
+            animateClose(x, y);
+        }
+        setExposed(false, mNeedsFalsingProtection);
+        if (mListener != null) {
+            mListener.onGutsClosed(this);
+        }
+    }
+
+    private void animateClose(int x, int y) {
         if (x == -1 || y == -1) {
             x = (getLeft() + getRight()) / 2;
             y = (getTop() + getHeight() / 2);
@@ -391,10 +206,6 @@
             }
         });
         a.start();
-        setExposed(false, mNeedsFalsingProtection);
-        if (mListener != null) {
-            mListener.onGutsClosed(this);
-        }
     }
 
     public void setActualHeight(int actualHeight) {
@@ -439,4 +250,14 @@
     public boolean isExposed() {
         return mExposed;
     }
+
+    @Override
+    public void onInteraction(View view) {
+        resetFalsingCheck();
+    }
+
+    @Override
+    public void closeGuts(View view) {
+        closeControls(-1 /* x */, -1 /* y */, true /* notify */);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
new file mode 100644
index 0000000..bdbc9b3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -0,0 +1,320 @@
+package com.android.systemui.statusbar;
+
+/*
+ * 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
+ */
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.app.INotificationManager;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.res.ColorStateList;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewAnimationUtils;
+import android.view.ViewGroup;
+import android.view.View.OnClickListener;
+import android.widget.CompoundButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.SeekBar;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settingslib.Utils;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.GutsContent;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.GutsInteractionListener;
+import com.android.systemui.statusbar.NotificationGuts.OnSettingsClickListener;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
+
+import java.util.Set;
+
+/**
+ * The guts of a notification revealed when performing a long press.
+ */
+public class NotificationInfo extends LinearLayout implements GutsContent {
+    private static final String TAG = "InfoGuts";
+
+    private INotificationManager mINotificationManager;
+    private int mStartingUserImportance;
+    private StatusBarNotification mStatusBarNotification;
+    private NotificationChannel mNotificationChannel;
+
+    private ImageView mAutoButton;
+    private TextView mImportanceSummary;
+    private TextView mImportanceTitle;
+    private boolean mAuto;
+
+    private View mImportanceGroup;
+    private View mChannelDisabled;
+    private Switch mChannelEnabledSwitch;
+    private RadioButton mMinImportanceButton;
+    private RadioButton mLowImportanceButton;
+    private RadioButton mDefaultImportanceButton;
+    private RadioButton mHighImportanceButton;
+
+    private GutsInteractionListener mGutsInteractionListener;
+
+    public NotificationInfo(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public interface OnSettingsClickListener {
+        void onClick(View v, int appUid);
+    }
+
+    public void bindNotification(final PackageManager pm,
+            final INotificationManager iNotificationManager,
+            final StatusBarNotification sbn, final NotificationChannel channel,
+            OnSettingsClickListener onSettingsClick,
+            OnClickListener onDoneClick, final Set<String> nonBlockablePkgs) {
+        mINotificationManager = iNotificationManager;
+        mNotificationChannel = channel;
+        mStatusBarNotification = sbn;
+        mStartingUserImportance = channel.getImportance();
+
+        final String pkg = sbn.getPackageName();
+        int appUid = -1;
+        String appname = pkg;
+        Drawable pkgicon = null;
+        try {
+            final ApplicationInfo info = pm.getApplicationInfo(pkg,
+                    PackageManager.MATCH_UNINSTALLED_PACKAGES
+                            | PackageManager.MATCH_DISABLED_COMPONENTS
+                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                            | PackageManager.MATCH_DIRECT_BOOT_AWARE);
+            if (info != null) {
+                appUid = info.uid;
+                appname = String.valueOf(pm.getApplicationLabel(info));
+                pkgicon = pm.getApplicationIcon(info);
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            // app is gone, just show package name and generic icon
+            pkgicon = pm.getDefaultActivityIcon();
+        }
+
+        // If this is the placeholder channel, don't use our channel-specific text.
+        String appNameText;
+        CharSequence channelNameText;
+        if (channel.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
+            appNameText = appname;
+            channelNameText = mContext.getString(R.string.notification_header_default_channel);
+        } else {
+            appNameText = mContext.getString(R.string.notification_importance_header_app, appname);
+            channelNameText = channel.getName();
+        }
+        ((TextView) findViewById(R.id.pkgname)).setText(appNameText);
+        ((TextView) findViewById(R.id.channel_name)).setText(channelNameText);
+
+        // Settings button.
+        final TextView settingsButton = (TextView) findViewById(R.id.more_settings);
+        if (appUid >= 0 && onSettingsClick != null) {
+            final int appUidF = appUid;
+            settingsButton.setOnClickListener(
+                    (View view) -> {
+                        onSettingsClick.onClick(view, appUidF);
+                    });
+            settingsButton.setText(R.string.notification_more_settings);
+        } else {
+            settingsButton.setVisibility(View.GONE);
+        }
+
+        // Done button.
+        final TextView doneButton = (TextView) findViewById(R.id.done);
+        doneButton.setText(R.string.notification_done);
+        doneButton.setOnClickListener(onDoneClick);
+
+        boolean nonBlockable = false;
+        try {
+            final PackageInfo info = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);
+            nonBlockable = Utils.isSystemPackage(getResources(), pm, info);
+        } catch (PackageManager.NameNotFoundException e) {
+            // unlikely.
+        }
+        if (nonBlockablePkgs != null) {
+            nonBlockable |= nonBlockablePkgs.contains(pkg);
+        }
+
+        final View importanceButtons = findViewById(R.id.importance_buttons);
+        bindToggles(importanceButtons, mStartingUserImportance, nonBlockable);
+
+        // Importance Text (hardcoded to 4 importance levels)
+        final ViewGroup importanceTextGroup = (ViewGroup) findViewById(
+                R.id.importance_buttons_text);
+        final int size = importanceTextGroup.getChildCount();
+        for (int i = 0; i < size; i++) {
+            int importanceNameResId = 0;
+            int importanceDescResId = 0;
+            switch (i) {
+                case 0:
+                    importanceNameResId = R.string.high_importance;
+                    importanceDescResId = R.string.notification_importance_high;
+                    break;
+                case 1:
+                    importanceNameResId = R.string.default_importance;
+                    importanceDescResId = R.string.notification_importance_default;
+                    break;
+                case 2:
+                    importanceNameResId = R.string.low_importance;
+                    importanceDescResId = R.string.notification_importance_low;
+                    break;
+                case 3:
+                    importanceNameResId = R.string.min_importance;
+                    importanceDescResId = R.string.notification_importance_min;
+                    break;
+                default:
+                    Log.e(TAG, "Too many importance groups in this layout.");
+                    break;
+            }
+            final ViewGroup importanceChildGroup = (ViewGroup) importanceTextGroup.getChildAt(i);
+            ((TextView) importanceChildGroup.getChildAt(0)).setText(importanceNameResId);
+            ((TextView) importanceChildGroup.getChildAt(1)).setText(importanceDescResId);
+        }
+
+        // Top-level importance group
+        mImportanceGroup = findViewById(R.id.importance);
+        mChannelDisabled = findViewById(R.id.channel_disabled);
+        updateImportanceGroup();
+    }
+
+    public boolean hasImportanceChanged() {
+        return mStartingUserImportance != getSelectedImportance();
+    }
+
+    public void saveImportance() {
+        int selectedImportance = getSelectedImportance();
+        if (selectedImportance == mStartingUserImportance) {
+            return;
+        }
+        MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
+                selectedImportance - mStartingUserImportance);
+        mNotificationChannel.setImportance(selectedImportance);
+        try {
+            mINotificationManager.updateNotificationChannelForPackage(
+                    mStatusBarNotification.getPackageName(), mStatusBarNotification.getUid(),
+                    mNotificationChannel);
+        } catch (RemoteException e) {
+            // :(
+        }
+    }
+
+    private int getSelectedImportance() {
+        if (!mChannelEnabledSwitch.isChecked()) {
+            return NotificationManager.IMPORTANCE_NONE;
+        } else if (mMinImportanceButton.isChecked()) {
+            return NotificationManager.IMPORTANCE_MIN;
+        } else if (mLowImportanceButton.isChecked()) {
+            return NotificationManager.IMPORTANCE_LOW;
+        } else if (mDefaultImportanceButton.isChecked()) {
+            return NotificationManager.IMPORTANCE_DEFAULT;
+        } else if (mHighImportanceButton.isChecked()) {
+            return NotificationManager.IMPORTANCE_HIGH;
+        } else {
+            return NotificationManager.IMPORTANCE_UNSPECIFIED;
+        }
+    }
+
+    private void bindToggles(final View importanceButtons, final int importance,
+            final boolean nonBlockable) {
+        // Enabled Switch
+        mChannelEnabledSwitch = (Switch) findViewById(R.id.channel_enabled_switch);
+        mChannelEnabledSwitch.setChecked(importance != NotificationManager.IMPORTANCE_NONE);
+        mChannelEnabledSwitch.setVisibility(nonBlockable ? View.INVISIBLE : View.VISIBLE);
+
+        // Importance Buttons
+        mMinImportanceButton = (RadioButton) importanceButtons.findViewById(R.id.min_importance);
+        mLowImportanceButton = (RadioButton) importanceButtons.findViewById(R.id.low_importance);
+        mDefaultImportanceButton = (RadioButton) importanceButtons
+                .findViewById(R.id.default_importance);
+        mHighImportanceButton = (RadioButton) importanceButtons.findViewById(R.id.high_importance);
+
+        // Set to current importance setting
+        switch (importance) {
+            case NotificationManager.IMPORTANCE_UNSPECIFIED:
+            case NotificationManager.IMPORTANCE_NONE:
+                break;
+            case NotificationManager.IMPORTANCE_MIN:
+                mMinImportanceButton.setChecked(true);
+                break;
+            case NotificationManager.IMPORTANCE_LOW:
+                mLowImportanceButton.setChecked(true);
+                break;
+            case NotificationManager.IMPORTANCE_DEFAULT:
+                mDefaultImportanceButton.setChecked(true);
+                break;
+            case NotificationManager.IMPORTANCE_HIGH:
+            case NotificationManager.IMPORTANCE_MAX:
+                mHighImportanceButton.setChecked(true);
+                break;
+        }
+
+        // Callback when checked.
+        mChannelEnabledSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
+            mGutsInteractionListener.onInteraction(NotificationInfo.this);
+            updateImportanceGroup();
+        });
+        ((RadioGroup) importanceButtons).setOnCheckedChangeListener(
+                (buttonView, isChecked) -> {
+                    mGutsInteractionListener.onInteraction(NotificationInfo.this);
+                });
+    }
+
+    private void updateImportanceGroup() {
+        final boolean disabled = getSelectedImportance() == NotificationManager.IMPORTANCE_NONE;
+        mImportanceGroup.setVisibility(disabled ? View.GONE : View.VISIBLE);
+        mChannelDisabled.setVisibility(disabled ? View.VISIBLE : View.GONE);
+    }
+
+    public void closeControls() {
+        if (mGutsInteractionListener != null) {
+            mGutsInteractionListener.closeGuts(this);
+        }
+    }
+
+    @Override
+    public void setInteractionListener(GutsInteractionListener listener) {
+        mGutsInteractionListener = listener;
+    }
+
+    @Override
+    public View getContentView() {
+        return this;
+    }
+
+    @Override
+    public boolean handleCloseControls() {
+        return false;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
new file mode 100644
index 0000000..fad63dd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
@@ -0,0 +1,392 @@
+/*
+ * 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.systemui.statusbar;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import java.util.ArrayList;
+
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.MenuItem;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.OnMenuClickListener;
+
+public class NotificationMenuRow extends FrameLayout
+        implements PluginListener<NotificationMenuRowProvider>, View.OnClickListener {
+
+    private static final int ICON_ALPHA_ANIM_DURATION = 200;
+
+    private ExpandableNotificationRow mParent;
+    private OnMenuClickListener mListener;
+    private NotificationMenuRowProvider mMenuProvider;
+    private ArrayList<MenuItem> mMenuItems = new ArrayList<>();
+
+    private ValueAnimator mFadeAnimator;
+    private boolean mMenuFadedIn = false;
+    private boolean mAnimating = false;
+    private boolean mOnLeft = true;
+    private boolean mDismissing = false;
+    private boolean mSnapping = false;
+    private boolean mIconsPlaced = false;
+
+    private int[] mIconLocation = new int[2];
+    private int[] mParentLocation = new int[2];
+
+    private float mHorizSpaceForIcon;
+    private int mVertSpaceForIcons;
+
+    private int mIconPadding;
+    private int mIconTint;
+
+    private float mAlpha = 0f;
+
+    public NotificationMenuRow(Context context) {
+        this(context, null);
+    }
+
+    public NotificationMenuRow(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public NotificationMenuRow(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public NotificationMenuRow(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs);
+        PluginManager.getInstance(getContext()).addPluginListener(
+                NotificationMenuRowProvider.ACTION, this,
+                NotificationMenuRowProvider.VERSION, false /* Allow multiple */);
+        mMenuItems.addAll(getDefaultNotificationMenuItems());
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        final Resources res = getResources();
+        mHorizSpaceForIcon = res.getDimensionPixelSize(R.dimen.notification_menu_icon_size);
+        mVertSpaceForIcons = res.getDimensionPixelSize(R.dimen.notification_min_height);
+        mIconPadding = res.getDimensionPixelSize(R.dimen.notification_menu_icon_padding);
+        mIconTint = res.getColor(R.color.notification_gear_color);
+        updateMenu(false /* notify */);
+    }
+
+    public static MenuItem getLongpressMenuItem(Context context) {
+        Resources res = context.getResources();
+        Drawable settingsIcon = res.getDrawable(R.drawable.ic_settings);
+        String settingsDescription = res.getString(R.string.notification_menu_gear_description);
+        NotificationInfo settingsContent = (NotificationInfo) LayoutInflater.from(context).inflate(
+                R.layout.notification_info, null, false);
+        MenuItem settings = new MenuItem(settingsIcon, settingsDescription, settingsContent);
+        return settings;
+    }
+
+    public ArrayList<MenuItem> getDefaultNotificationMenuItems() {
+        ArrayList<MenuItem> items = new ArrayList<MenuItem>();
+        Resources res = getResources();
+
+        Drawable snoozeIcon = res.getDrawable(R.drawable.ic_snooze);
+        NotificationSnooze content = (NotificationSnooze) LayoutInflater.from(mContext)
+                .inflate(R.layout.notification_snooze, null, false);
+        String snoozeDescription = res.getString(R.string.notification_menu_snooze_description);
+        MenuItem snooze = new MenuItem(snoozeIcon, snoozeDescription, content);
+        items.add(snooze);
+
+        Drawable settingsIcon = res.getDrawable(R.drawable.ic_settings);
+        String settingsDescription = res.getString(R.string.notification_menu_gear_description);
+        NotificationInfo settingsContent = (NotificationInfo) LayoutInflater.from(mContext).inflate(
+                R.layout.notification_info, null, false);
+        MenuItem settings = new MenuItem(settingsIcon, settingsDescription, settingsContent);
+        items.add(settings);
+        return items;
+    }
+
+    private void updateMenu(boolean notify) {
+        removeAllViews();
+        mMenuItems.clear();
+        if (mMenuProvider != null) {
+            mMenuItems.addAll(mMenuProvider.getMenuItems(getContext()));
+        }
+        mMenuItems.addAll(getDefaultNotificationMenuItems());
+        for (int i = 0; i < mMenuItems.size(); i++) {
+            final View v = createMenuView(mMenuItems.get(i));
+            mMenuItems.get(i).menuView = v;
+        }
+        resetState(notify);
+    }
+
+    private View createMenuView(MenuItem item) {
+        AlphaOptimizedImageView iv = new AlphaOptimizedImageView(getContext());
+        addView(iv);
+        iv.setPadding(mIconPadding, mIconPadding, mIconPadding, mIconPadding);
+        iv.setImageDrawable(item.icon);
+        iv.setOnClickListener(this);
+        iv.setColorFilter(mIconTint);
+        iv.setAlpha(mAlpha);
+        FrameLayout.LayoutParams lp = (LayoutParams) iv.getLayoutParams();
+        lp.width = (int) mHorizSpaceForIcon;
+        lp.height = (int) mHorizSpaceForIcon;
+        return iv;
+    }
+
+    public void resetState(boolean notify) {
+        setMenuAlpha(0f);
+        mIconsPlaced = false;
+        mMenuFadedIn = false;
+        mAnimating = false;
+        mSnapping = false;
+        mDismissing = false;
+        setMenuLocation(mOnLeft ? 1 : -1 /* on left */);
+        if (mListener != null && notify) {
+            mListener.onMenuReset(mParent);
+        }
+    }
+
+    public void setMenuClickListener(OnMenuClickListener listener) {
+        mListener = listener;
+    }
+
+    public void setNotificationRowParent(ExpandableNotificationRow parent) {
+        mParent = parent;
+        setMenuLocation(mOnLeft ? 1 : -1);
+    }
+
+    public void setAppName(String appName) {
+        Resources res = getResources();
+        final int count = mMenuItems.size();
+        for (int i = 0; i < count; i++) {
+            MenuItem item = mMenuItems.get(i);
+            String description = String.format(
+                    res.getString(R.string.notification_menu_accessibility),
+                    appName, item.menuDescription);
+            item.menuView.setContentDescription(description);
+        }
+    }
+
+    public ExpandableNotificationRow getNotificationParent() {
+        return mParent;
+    }
+
+    public void setMenuAlpha(float alpha) {
+        mAlpha = alpha;
+        if (alpha == 0) {
+            mMenuFadedIn = false; // Can fade in again once it's gone.
+            setVisibility(View.INVISIBLE);
+        } else {
+            setVisibility(View.VISIBLE);
+        }
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            getChildAt(i).setAlpha(mAlpha);
+        }
+    }
+
+    /**
+     * Returns whether the menu is displayed on the left side of the view or not.
+     */
+    public boolean isMenuOnLeft() {
+        return mOnLeft;
+    }
+
+    /**
+     * Returns the horizontal space in pixels required to display the menu.
+     */
+    public float getSpaceForMenu() {
+        return mHorizSpaceForIcon * getChildCount();
+    }
+
+    /**
+     * Indicates whether the menu is visible at 1 alpha. Does not indicate if entire view is
+     * visible.
+     */
+    public boolean isVisible() {
+        return mAlpha > 0;
+    }
+
+    public void cancelFadeAnimator() {
+        if (mFadeAnimator != null) {
+            mFadeAnimator.cancel();
+        }
+    }
+
+    public void updateMenuAlpha(final float transX, final float size) {
+        if (mAnimating || !mMenuFadedIn) {
+            // Don't adjust when animating, or if the menu hasn't been shown yet.
+            return;
+        }
+
+        final float fadeThreshold = size * 0.3f;
+        final float absTrans = Math.abs(transX);
+        float desiredAlpha = 0;
+
+        if (absTrans == 0) {
+            desiredAlpha = 0;
+        } else if (absTrans <= fadeThreshold) {
+            desiredAlpha = 1;
+        } else {
+            desiredAlpha = 1 - ((absTrans - fadeThreshold) / (size - fadeThreshold));
+        }
+        setMenuAlpha(desiredAlpha);
+    }
+
+    public void fadeInMenu(final boolean fromLeft, final float transX,
+            final float notiThreshold) {
+        if (mDismissing || mAnimating) {
+            return;
+        }
+        if (isMenuLocationChange(transX)) {
+            setMenuAlpha(0f);
+        }
+        setMenuLocation((int) transX);
+        mFadeAnimator = ValueAnimator.ofFloat(mAlpha, 1);
+        mFadeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                final float absTrans = Math.abs(transX);
+
+                boolean pastGear = (fromLeft && transX <= notiThreshold)
+                        || (!fromLeft && absTrans <= notiThreshold);
+                if (pastGear && !mMenuFadedIn) {
+                    setMenuAlpha((float) animation.getAnimatedValue());
+                }
+            }
+        });
+        mFadeAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mAnimating = true;
+            }
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                // TODO should animate back to 0f from current alpha
+                setMenuAlpha(0f);
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mAnimating = false;
+                mMenuFadedIn = mAlpha == 1;
+            }
+        });
+        mFadeAnimator.setInterpolator(Interpolators.ALPHA_IN);
+        mFadeAnimator.setDuration(ICON_ALPHA_ANIM_DURATION);
+        mFadeAnimator.start();
+    }
+
+    public void updateVerticalLocation() {
+        if (mParent == null || mMenuItems.size() == 0) {
+            return;
+        }
+        int parentHeight = mParent.getCollapsedHeight();
+        float translationY;
+        if (parentHeight < mVertSpaceForIcons) {
+            translationY = (parentHeight / 2) - (mHorizSpaceForIcon / 2);
+        } else {
+            translationY = (mVertSpaceForIcons - mHorizSpaceForIcon) / 2;
+        }
+        setTranslationY(translationY);
+    }
+
+    @Override
+    public void onRtlPropertiesChanged(int layoutDirection) {
+        mIconsPlaced = false;
+        setMenuLocation(mOnLeft ? 1 : -1);
+    }
+
+    public void setMenuLocation(int translation) {
+        boolean onLeft = translation > 0;
+        if ((mIconsPlaced && onLeft == mOnLeft) || mSnapping || mParent == null) {
+            // Do nothing
+            return;
+        }
+        final boolean isRtl = mParent.isLayoutRtl();
+        final int count = getChildCount();
+        final int width = getWidth();
+        for (int i = 0; i < count; i++) {
+            final View v = getChildAt(i);
+            final float left = isRtl
+                    ? -(width - mHorizSpaceForIcon * (i + 1))
+                    : i * mHorizSpaceForIcon;
+            final float right = isRtl
+                    ? -i * mHorizSpaceForIcon
+                    : width - (mHorizSpaceForIcon * (i + 1));
+            v.setTranslationX(onLeft ? left : right);
+        }
+        mOnLeft = onLeft;
+        mIconsPlaced = true;
+    }
+
+    public boolean isMenuLocationChange(float translation) {
+        boolean onLeft = translation > mIconPadding;
+        boolean onRight = translation < -mIconPadding;
+        if ((mOnLeft && onRight) || (!mOnLeft && onLeft)) {
+            return true;
+        }
+        return false;
+    }
+
+    public void setDismissing() {
+        mDismissing = true;
+    }
+
+    public void setSnapping(boolean snapping) {
+        mSnapping = snapping;
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (mListener == null) {
+            // Nothing to do
+            return;
+        }
+        v.getLocationOnScreen(mIconLocation);
+        mParent.getLocationOnScreen(mParentLocation);
+        final int centerX = (int) (mHorizSpaceForIcon / 2);
+        final int centerY = (int) (v.getTranslationY() * 2 + v.getHeight()) / 2;
+        final int x = mIconLocation[0] - mParentLocation[0] + centerX;
+        final int y = mIconLocation[1] - mParentLocation[1] + centerY;
+        final int index = indexOfChild(v);
+        mListener.onMenuClicked(mParent, x, y, mMenuItems.get(index));
+    }
+
+    @Override
+    public void onPluginConnected(NotificationMenuRowProvider plugin, Context pluginContext) {
+        mMenuProvider = plugin;
+        updateMenu(false /* notify */);
+    }
+
+    @Override
+    public void onPluginDisconnected(NotificationMenuRowProvider plugin) {
+        mMenuProvider = null;
+        updateMenu(false /* notify */);
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
deleted file mode 100644
index 4315647..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
+++ /dev/null
@@ -1,300 +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 com.android.systemui.statusbar;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.content.res.Resources;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-
-public class NotificationSettingsIconRow extends FrameLayout implements View.OnClickListener {
-
-    private static final int GEAR_ALPHA_ANIM_DURATION = 200;
-
-    public interface SettingsIconRowListener {
-        /**
-         * Called when the gear behind a notification is touched.
-         */
-        public void onGearTouched(ExpandableNotificationRow row, int x, int y);
-
-        /**
-         * Called when a notification is slid back over the gear.
-         */
-        public void onSettingsIconRowReset(ExpandableNotificationRow row);
-    }
-
-    private ExpandableNotificationRow mParent;
-    private AlphaOptimizedImageView mGearIcon;
-    private float mHorizSpaceForGear;
-    private SettingsIconRowListener mListener;
-
-    private ValueAnimator mFadeAnimator;
-    private boolean mSettingsFadedIn = false;
-    private boolean mAnimating = false;
-    private boolean mOnLeft = true;
-    private boolean mDismissing = false;
-    private boolean mSnapping = false;
-    private boolean mIconPlaced = false;
-
-    private int[] mGearLocation = new int[2];
-    private int[] mParentLocation = new int[2];
-    private int mVertSpaceForGear;
-
-    public NotificationSettingsIconRow(Context context) {
-        this(context, null);
-    }
-
-    public NotificationSettingsIconRow(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public NotificationSettingsIconRow(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public NotificationSettingsIconRow(Context context, AttributeSet attrs, int defStyleAttr,
-            int defStyleRes) {
-        super(context, attrs);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mGearIcon = (AlphaOptimizedImageView) findViewById(R.id.gear_icon);
-        mGearIcon.setOnClickListener(this);
-        setOnClickListener(this);
-        mHorizSpaceForGear =
-                getResources().getDimensionPixelOffset(R.dimen.notification_gear_width);
-        mVertSpaceForGear = getResources().getDimensionPixelOffset(R.dimen.notification_min_height);
-        resetState();
-    }
-
-    public void resetState() {
-        setGearAlpha(0f);
-        mIconPlaced = false;
-        mSettingsFadedIn = false;
-        mAnimating = false;
-        mSnapping = false;
-        mDismissing = false;
-        setIconLocation(true /* on left */);
-        if (mListener != null) {
-            mListener.onSettingsIconRowReset(mParent);
-        }
-    }
-
-    public void setGearListener(SettingsIconRowListener listener) {
-        mListener = listener;
-    }
-
-    public void setNotificationRowParent(ExpandableNotificationRow parent) {
-        mParent = parent;
-        setIconLocation(mOnLeft);
-    }
-
-    public void setAppName(String appName) {
-        Resources res = getResources();
-        String description = String.format(res.getString(R.string.notification_gear_accessibility),
-                appName);
-        mGearIcon.setContentDescription(description);
-    }
-
-    public ExpandableNotificationRow getNotificationParent() {
-        return mParent;
-    }
-
-    public void setGearAlpha(float alpha) {
-        if (alpha == 0) {
-            mSettingsFadedIn = false; // Can fade in again once it's gone.
-            setVisibility(View.INVISIBLE);
-        } else {
-            setVisibility(View.VISIBLE);
-        }
-        mGearIcon.setAlpha(alpha);
-    }
-
-    /**
-     * Returns whether the icon is on the left side of the view or not.
-     */
-    public boolean isIconOnLeft() {
-        return mOnLeft;
-    }
-
-    /**
-     * Returns the horizontal space in pixels required to display the gear behind a notification.
-     */
-    public float getSpaceForGear() {
-        return mHorizSpaceForGear;
-    }
-
-    /**
-     * Indicates whether the gear is visible at 1 alpha. Does not indicate
-     * if entire view is visible.
-     */
-    public boolean isVisible() {
-        return mGearIcon.getAlpha() > 0;
-    }
-
-    public void cancelFadeAnimator() {
-        if (mFadeAnimator != null) {
-            mFadeAnimator.cancel();
-        }
-    }
-
-    public void updateSettingsIcons(final float transX, final float size) {
-        if (mAnimating || !mSettingsFadedIn) {
-            // Don't adjust when animating, or if the gear hasn't been shown yet.
-            return;
-        }
-
-        final float fadeThreshold = size * 0.3f;
-        final float absTrans = Math.abs(transX);
-        float desiredAlpha = 0;
-
-        if (absTrans == 0) {
-            desiredAlpha = 0;
-        } else if (absTrans <= fadeThreshold) {
-            desiredAlpha = 1;
-        } else {
-            desiredAlpha = 1 - ((absTrans - fadeThreshold) / (size - fadeThreshold));
-        }
-        setGearAlpha(desiredAlpha);
-    }
-
-    public void fadeInSettings(final boolean fromLeft, final float transX,
-            final float notiThreshold) {
-        if (mDismissing || mAnimating) {
-            return;
-        }
-        if (isIconLocationChange(transX)) {
-            setGearAlpha(0f);
-        }
-        setIconLocation(transX > 0 /* fromLeft */);
-        mFadeAnimator = ValueAnimator.ofFloat(mGearIcon.getAlpha(), 1);
-        mFadeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                final float absTrans = Math.abs(transX);
-
-                boolean pastGear = (fromLeft && transX <= notiThreshold)
-                        || (!fromLeft && absTrans <= notiThreshold);
-                if (pastGear && !mSettingsFadedIn) {
-                    setGearAlpha((float) animation.getAnimatedValue());
-                }
-            }
-        });
-        mFadeAnimator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationStart(Animator animation) {
-                mAnimating = true;
-            }
-
-            @Override
-            public void onAnimationCancel(Animator animation) {
-                // TODO should animate back to 0f from current alpha
-                mGearIcon.setAlpha(0f);
-            }
-
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mAnimating = false;
-                mSettingsFadedIn = mGearIcon.getAlpha() == 1;
-            }
-        });
-        mFadeAnimator.setInterpolator(Interpolators.ALPHA_IN);
-        mFadeAnimator.setDuration(GEAR_ALPHA_ANIM_DURATION);
-        mFadeAnimator.start();
-    }
-
-    public void updateVerticalLocation() {
-        if (mParent == null) {
-            return;
-        }
-        int parentHeight = mParent.getCollapsedHeight();
-        if (parentHeight < mVertSpaceForGear) {
-            mGearIcon.setTranslationY((parentHeight / 2) - (mGearIcon.getHeight() / 2));
-        } else {
-            mGearIcon.setTranslationY((mVertSpaceForGear - mGearIcon.getHeight()) / 2);
-        }
-    }
-
-    @Override
-    public void onRtlPropertiesChanged(int layoutDirection) {
-        setIconLocation(mOnLeft);
-    }
-
-    public void setIconLocation(boolean onLeft) {
-        if ((mIconPlaced && onLeft == mOnLeft) || mSnapping || mParent == null
-                || mGearIcon.getWidth() == 0) {
-            // Do nothing
-            return;
-        }
-        final boolean isRtl = mParent.isLayoutRtl();
-        final float left = isRtl
-                ? -(mParent.getWidth() - mHorizSpaceForGear)
-                : 0;
-        final float right = isRtl
-                ? 0
-                : mParent.getWidth() - mHorizSpaceForGear;
-        final float centerX = ((mHorizSpaceForGear - mGearIcon.getWidth()) / 2);
-        setTranslationX(onLeft ? left + centerX : right + centerX);
-        mOnLeft = onLeft;
-        mIconPlaced = true;
-    }
-
-    public boolean isIconLocationChange(float translation) {
-        boolean onLeft = translation > mGearIcon.getPaddingStart();
-        boolean onRight = translation < -mGearIcon.getPaddingStart();
-        if ((mOnLeft && onRight) || (!mOnLeft && onLeft)) {
-            return true;
-        }
-        return false;
-    }
-
-    public void setDismissing() {
-        mDismissing = true;
-    }
-
-    public void setSnapping(boolean snapping) {
-        mSnapping = snapping;
-    }
-
-    @Override
-    public void onClick(View v) {
-        if (v.getId() == R.id.gear_icon) {
-            if (mListener != null) {
-                mGearIcon.getLocationOnScreen(mGearLocation);
-                mParent.getLocationOnScreen(mParentLocation);
-
-                final int centerX = (int) (mHorizSpaceForGear / 2);
-                final int centerY =
-                        (int) (mGearIcon.getTranslationY() * 2 + mGearIcon.getHeight())/ 2;
-                final int x = mGearLocation[0] - mParentLocation[0] + centerX;
-                final int y = mGearLocation[1] - mParentLocation[1] + centerY;
-                mListener.onGearTouched(mParent, x, y);
-            }
-        } else {
-            // Do nothing when the background is touched.
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
new file mode 100644
index 0000000..1992b6c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSnooze.java
@@ -0,0 +1,211 @@
+package com.android.systemui.statusbar;
+/*
+ * 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
+ */
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.GutsInteractionListener;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.SnoozeListener;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.SnoozeOption;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.service.notification.SnoozeCriterion;
+import android.service.notification.StatusBarNotification;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.ContextThemeWrapper;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RadioGroup;
+import android.widget.RadioGroup.OnCheckedChangeListener;
+import android.widget.TextView;
+import android.widget.Toast;
+import com.android.systemui.R;
+
+public class NotificationSnooze extends LinearLayout
+        implements NotificationMenuRowProvider.SnoozeGutsContent, View.OnClickListener {
+
+    private static final int MAX_ASSISTANT_SUGGESTIONS = 2;
+    private GutsInteractionListener mGutsInteractionListener;
+    private SnoozeListener mSnoozeListener;
+    private StatusBarNotification mSbn;
+
+    private TextView mSelectedOptionText;
+    private TextView mUndoButton;
+    private ViewGroup mSnoozeOptionView;
+    private List<SnoozeOption> mSnoozeOptions;
+
+    private SnoozeOption mSelectedOption;
+
+    public NotificationSnooze(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        // Create the different options based on list
+        mSnoozeOptions = getDefaultSnoozeOptions();
+        createOptionViews();
+
+        // Snackbar
+        mSelectedOptionText = (TextView) findViewById(R.id.snooze_option_default);
+        mSelectedOptionText.setOnClickListener(this);
+        mUndoButton = (TextView) findViewById(R.id.undo);
+        mUndoButton.setOnClickListener(this);
+
+        // Default to first option in list
+        setSelected(mSnoozeOptions.get(0));
+    }
+
+    public void setSnoozeOptions(final List<SnoozeCriterion> snoozeList) {
+        if (snoozeList == null) {
+            return;
+        }
+        mSnoozeOptions.clear();
+        mSnoozeOptions = getDefaultSnoozeOptions();
+        final int count = Math.min(MAX_ASSISTANT_SUGGESTIONS, snoozeList.size());
+        for (int i = 0; i < count; i++) {
+            SnoozeCriterion sc = snoozeList.get(i);
+            mSnoozeOptions.add(new SnoozeOption(sc, 0, sc.getExplanation(), sc.getConfirmation()));
+        }
+        createOptionViews();
+    }
+
+    private ArrayList<SnoozeOption> getDefaultSnoozeOptions() {
+        ArrayList<SnoozeOption> options = new ArrayList<>();
+        options.add(createOption(R.string.snooze_option_15_min, 15));
+        options.add(createOption(R.string.snooze_option_30_min, 30));
+        options.add(createOption(R.string.snooze_option_1_hour, 60));
+        return options;
+    }
+
+    private SnoozeOption createOption(int descriptionResId, int minutes) {
+        Resources res = getResources();
+        String resultText = String.format(
+                res.getString(R.string.snoozed_for_time), res.getString(descriptionResId));
+        return new SnoozeOption(null, minutes, res.getString(descriptionResId), resultText);
+    }
+
+    private void createOptionViews() {
+        mSnoozeOptionView = (ViewGroup) findViewById(R.id.snooze_options);
+        mSnoozeOptionView.removeAllViews();
+        mSnoozeOptionView.setVisibility(View.GONE);
+        final Resources res = getResources();
+        final int textSize = res.getDimensionPixelSize(R.dimen.snooze_option_text_size);
+        final int p = res.getDimensionPixelSize(R.dimen.snooze_option_padding);
+
+        // Add all the options
+        for (int i = 0; i < mSnoozeOptions.size(); i++) {
+            SnoozeOption option = mSnoozeOptions.get(i);
+            TextView tv = new TextView(getContext());
+            tv.setTextColor(Color.WHITE);
+            tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
+            tv.setPadding(p, p, p, p);
+            mSnoozeOptionView.addView(tv);
+            tv.setText(option.description);
+            tv.setTag(option);
+            tv.setOnClickListener(this);
+        }
+
+        // Add the undo option as final item
+        TextView tv = new TextView(getContext());
+        tv.setTextColor(Color.WHITE);
+        tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
+        tv.setPadding(p, p, p, p);
+        mSnoozeOptionView.addView(tv);
+        tv.setText(R.string.snooze_option_dont_snooze);
+        tv.setOnClickListener(this);
+    }
+
+    private void showSnoozeOptions(boolean show) {
+        mSelectedOptionText.setVisibility(show ? View.GONE : View.VISIBLE);
+        mUndoButton.setVisibility(show ? View.GONE : View.VISIBLE);
+        mSnoozeOptionView.setVisibility(show ? View.VISIBLE : View.GONE);
+    }
+
+    private void setSelected(SnoozeOption option) {
+        mSelectedOption = option;
+        mSelectedOptionText.setText(option.confirmation);
+        showSnoozeOptions(false);
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (mGutsInteractionListener != null) {
+            mGutsInteractionListener.onInteraction(this);
+        }
+        final int id = v.getId();
+        final SnoozeOption tag = (SnoozeOption) v.getTag();
+        if (tag != null) {
+            setSelected(tag);
+        } else if (id == R.id.snooze_option_default) {
+            // Show more snooze options
+            showSnoozeOptions(true);
+        } else {
+            undoSnooze();
+        }
+    }
+
+    private void undoSnooze() {
+        mSelectedOption = null;
+        mGutsInteractionListener.closeGuts(this);
+    }
+
+    @Override
+    public View getContentView() {
+        return this;
+    }
+
+    @Override
+    public void setStatusBarNotification(StatusBarNotification sbn) {
+        mSbn = sbn;
+    }
+
+    @Override
+    public void setInteractionListener(GutsInteractionListener listener) {
+        mGutsInteractionListener = listener;
+    }
+
+    @Override
+    public void setSnoozeListener(SnoozeListener listener) {
+        mSnoozeListener = listener;
+    }
+
+    @Override
+    public boolean handleCloseControls() {
+        // When snooze is closed (i.e. there was interaction outside of the notification)
+        // then we commit the snooze action.
+        if (mSnoozeListener != null && mSelectedOption != null) {
+            mSnoozeListener.snoozeNotification(mSbn, mSelectedOption);
+            return true;
+        } else {
+            // Reset the view once it's closed
+            setSelected(mSnoozeOptions.get(0));
+            showSnoozeOptions(false);
+        }
+        return false;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index c8e8973..9a76ad6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -273,7 +273,7 @@
     @Override
     public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
             int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
-            String description, boolean isWide, int subId) {
+            String description, boolean isWide, int subId, boolean roaming) {
         PhoneState state = getState(subId);
         if (state == null) {
             return;
@@ -284,6 +284,7 @@
         state.mMobileDescription = statusIcon.contentDescription;
         state.mMobileTypeDescription = typeContentDescription;
         state.mIsMobileTypeIconWide = statusType != 0 && isWide;
+        state.mRoaming = roaming;
 
         apply();
     }
@@ -631,7 +632,8 @@
         private String mMobileDescription, mMobileTypeDescription;
 
         private ViewGroup mMobileGroup;
-        private ImageView mMobile, mMobileDark, mMobileType;
+        private ImageView mMobile, mMobileDark, mMobileType, mMobileRoaming;
+        public boolean mRoaming;
 
         public PhoneState(int subId, Context context) {
             ViewGroup root = (ViewGroup) LayoutInflater.from(context)
@@ -645,6 +647,7 @@
             mMobile         = (ImageView) root.findViewById(R.id.mobile_signal);
             mMobileDark     = (ImageView) root.findViewById(R.id.mobile_signal_dark);
             mMobileType     = (ImageView) root.findViewById(R.id.mobile_type);
+            mMobileRoaming  = (ImageView) root.findViewById(R.id.mobile_roaming);
         }
 
         public boolean apply(boolean isSecondaryIcon) {
@@ -680,6 +683,7 @@
                         (mMobileVisible ? "VISIBLE" : "GONE"), mMobileStrengthId, mMobileTypeId));
 
             mMobileType.setVisibility(mMobileTypeId != 0 ? View.VISIBLE : View.GONE);
+            mMobileRoaming.setVisibility(mRoaming ? View.VISIBLE : View.GONE);
 
             return mMobileVisible;
         }
@@ -739,6 +743,8 @@
                     StatusBarIconController.getDarkIntensity(tintArea, mMobile, darkIntensity),
                     mMobile, mMobileDark);
             setTint(mMobileType, StatusBarIconController.getTint(tintArea, mMobileType, tint));
+            setTint(mMobileRoaming, StatusBarIconController.getTint(tintArea, mMobileRoaming,
+                    tint));
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
index cd6c31f..1c89e32 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
@@ -23,6 +23,7 @@
 import android.util.ArraySet;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.animation.Interpolator;
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
@@ -298,5 +299,14 @@
                 TransformState otherState) {
             return false;
         }
+
+        /**
+         * Get a custom interpolator for this animation
+         * @param interpolationType the type of the interpolation, i.e TranslationX / TranslationY
+         * @param isFrom true if this transformation from the other view
+         */
+        public Interpolator getCustomInterpolator(int interpolationType, boolean isFrom) {
+            return null;
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index f24e40b..f6a5687 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -39,7 +39,7 @@
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
 import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.PhoneStatusBarView;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
@@ -47,7 +47,7 @@
 /**
  * A status bar (and navigation bar) tailored for the automotive use case.
  */
-public class CarStatusBar extends PhoneStatusBar implements
+public class CarStatusBar extends StatusBar implements
         CarBatteryController.BatteryViewHandler {
     private static final String TAG = "CarStatusBar";
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
index c308930..67f8426 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
@@ -20,7 +20,7 @@
 import com.android.systemui.statusbar.ScalingDrawableWrapper;
 import com.android.systemui.statusbar.policy.BluetoothController;
 
-import static com.android.systemui.statusbar.phone.PhoneStatusBar.DEBUG;
+import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
 
 /**
  * Controller that monitors signal strength for a device that is connected via bluetooth.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index 8e6c153..f8b6dee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -20,7 +20,7 @@
 import android.view.ViewStub;
 
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 
 /**
@@ -32,7 +32,7 @@
     private UserGridView mUserGridView;
     private UserSwitcherController mUserSwitcherController;
 
-    public FullscreenUserSwitcher(PhoneStatusBar statusBar,
+    public FullscreenUserSwitcher(StatusBar statusBar,
             UserSwitcherController userSwitcherController,
             ViewStub containerStub) {
         mUserSwitcherController = userSwitcherController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
index d90a21d..137b5cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
@@ -29,12 +29,12 @@
 
 import com.android.systemui.R;
 import com.android.systemui.statusbar.UserUtil;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 
 public class UserGridView extends GridView {
 
-    private PhoneStatusBar mStatusBar;
+    private StatusBar mStatusBar;
     private UserSwitcherController mUserSwitcherController;
     private Adapter mAdapter;
     private int mPendingUserId = UserHandle.USER_NULL;
@@ -43,7 +43,7 @@
         super(context, attrs);
     }
 
-    public void init(PhoneStatusBar statusBar, UserSwitcherController userSwitcherController) {
+    public void init(StatusBar statusBar, UserSwitcherController userSwitcherController) {
         mStatusBar = statusBar;
         mUserSwitcherController = userSwitcherController;
         mAdapter = new Adapter(mUserSwitcherController);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/CustomInterpolatorTransformation.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/CustomInterpolatorTransformation.java
new file mode 100644
index 0000000..de4c312
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/CustomInterpolatorTransformation.java
@@ -0,0 +1,79 @@
+/*
+ * 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.notification;
+
+import android.view.View;
+import android.view.animation.Interpolator;
+
+import com.android.systemui.Interpolators;
+import com.android.systemui.statusbar.CrossFadeHelper;
+import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.ViewTransformationHelper;
+
+import static com.android.systemui.statusbar.TransformableView.TRANSFORMING_VIEW_TITLE;
+import static com.android.systemui.statusbar.notification.TransformState.TRANSFORM_Y;
+
+/**
+ * A custom transformation that modifies the interpolator
+ */
+public abstract class CustomInterpolatorTransformation
+        extends ViewTransformationHelper.CustomTransformation {
+
+    private final int mViewType;
+
+    public CustomInterpolatorTransformation(int viewType) {
+        mViewType = viewType;
+    }
+
+    @Override
+    public boolean transformTo(TransformState ownState, TransformableView notification,
+            float transformationAmount) {
+        if (!hasCustomTransformation()) {
+            return false;
+        }
+        TransformState otherState = notification.getCurrentState(mViewType);
+        if (otherState == null) {
+            return false;
+        }
+        View view = ownState.getTransformedView();
+        CrossFadeHelper.fadeOut(view, transformationAmount);
+        ownState.transformViewFullyTo(otherState, this, transformationAmount);
+        otherState.recycle();
+        return true;
+    }
+
+    protected boolean hasCustomTransformation() {
+        return true;
+    }
+
+    @Override
+    public boolean transformFrom(TransformState ownState,
+            TransformableView notification, float transformationAmount) {
+        if (!hasCustomTransformation()) {
+            return false;
+        }
+        TransformState otherState = notification.getCurrentState(mViewType);
+        if (otherState == null) {
+            return false;
+        }
+        View view = ownState.getTransformedView();
+        CrossFadeHelper.fadeIn(view, transformationAmount);
+        ownState.transformViewFullyFrom(otherState, this, transformationAmount);
+        otherState.recycle();
+        return true;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
index d564741..3b18886 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
@@ -40,9 +40,6 @@
 
     private final ViewInvertHelper mInvertHelper;
     private final Paint mGreyPaint = new Paint();
-    private int mBackgroundColor = 0;
-    private static final int CUSTOM_BACKGROUND_TAG = R.id.custom_background_color;
-    private boolean mShouldInvertDark;
     private boolean mShowingLegacyBackground;
 
     protected NotificationCustomViewWrapper(View view, ExpandableNotificationRow row) {
@@ -106,32 +103,6 @@
     }
 
     @Override
-    public void notifyContentUpdated(StatusBarNotification notification, boolean isLowPriority) {
-        super.notifyContentUpdated(notification, isLowPriority);
-        Drawable background = mView.getBackground();
-        mBackgroundColor = 0;
-        if (background instanceof ColorDrawable) {
-            mBackgroundColor = ((ColorDrawable) background).getColor();
-            mView.setBackground(null);
-            mView.setTag(CUSTOM_BACKGROUND_TAG, mBackgroundColor);
-        } else if (mView.getTag(CUSTOM_BACKGROUND_TAG) != null) {
-            mBackgroundColor = (int) mView.getTag(CUSTOM_BACKGROUND_TAG);
-        }
-        mShouldInvertDark = mBackgroundColor == 0 || isColorLight(mBackgroundColor);
-    }
-
-    private boolean isColorLight(int backgroundColor) {
-        return Color.alpha(backgroundColor) == 0
-                || ColorUtils.calculateLuminance(backgroundColor) > 0.5;
-    }
-
-    @Override
-    public int getCustomBackgroundColor() {
-        // Parent notifications should always use the normal background color
-        return mRow.isSummaryWithChildren() ? 0 : mBackgroundColor;
-    }
-
-    @Override
     public void setShowingLegacyBackground(boolean showing) {
         super.setShowingLegacyBackground(showing);
         mShowingLegacyBackground = showing;
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 e1f553c..8eab2e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
@@ -31,9 +31,12 @@
 import android.view.NotificationHeaderView;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.animation.Interpolator;
+import android.view.animation.PathInterpolator;
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.ViewInvertHelper;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -43,17 +46,21 @@
 
 import java.util.Stack;
 
+import static com.android.systemui.statusbar.notification.TransformState.TRANSFORM_Y;
+
 /**
  * Wraps a notification header view.
  */
 public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
 
+    private static final Interpolator LOW_PRIORITY_HEADER_CLOSE
+            = new PathInterpolator(0.4f, 0f, 0.7f, 1f);
     private final PorterDuffColorFilter mIconColorFilter = new PorterDuffColorFilter(
             0, PorterDuff.Mode.SRC_ATOP);
     private final int mIconDarkAlpha;
     private final int mIconDarkColor = 0xffffffff;
-    protected final ViewInvertHelper mInvertHelper;
 
+    protected final ViewInvertHelper mInvertHelper;
     protected final ViewTransformationHelper mTransformationHelper;
 
     protected int mColor;
@@ -70,6 +77,32 @@
         mIconDarkAlpha = ctx.getResources().getInteger(R.integer.doze_small_icon_alpha);
         mInvertHelper = new ViewInvertHelper(ctx, NotificationPanelView.DOZE_ANIMATION_DURATION);
         mTransformationHelper = new ViewTransformationHelper();
+
+        // we want to avoid that the header clashes with the other text when transforming
+        // low-priority
+        mTransformationHelper.setCustomTransformation(
+                new CustomInterpolatorTransformation(TRANSFORMING_VIEW_TITLE) {
+
+                    @Override
+                    public Interpolator getCustomInterpolator(int interpolationType,
+                            boolean isFrom) {
+                        boolean isLowPriority = mView instanceof NotificationHeaderView;
+                        if (interpolationType == TRANSFORM_Y) {
+                            if (isLowPriority && !isFrom
+                                    || !isLowPriority && isFrom) {
+                                return Interpolators.LINEAR_OUT_SLOW_IN;
+                            } else {
+                                return LOW_PRIORITY_HEADER_CLOSE;
+                            }
+                        }
+                        return null;
+                    }
+
+                    @Override
+                    protected boolean hasCustomTransformation() {
+                        return mIsLowPriority;
+                    }
+                }, TRANSFORMING_VIEW_TITLE);
         resolveHeaderViews();
         updateInvertHelper();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java
index 61457df..defeab2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java
@@ -22,7 +22,11 @@
 
 import android.content.Context;
 import android.service.notification.StatusBarNotification;
+import android.text.TextUtils;
 import android.view.View;
+import android.widget.TextView;
+
+import java.util.ArrayList;
 
 /**
  * Wraps a notification containing a messaging template
@@ -30,6 +34,7 @@
 public class NotificationMessagingTemplateViewWrapper extends NotificationTemplateViewWrapper {
 
     private View mContractedMessage;
+    private ArrayList<View> mHistoricMessages = new ArrayList<View>();
 
     protected NotificationMessagingTemplateViewWrapper(Context ctx, View view,
             ExpandableNotificationRow row) {
@@ -44,11 +49,18 @@
                 && ((MessagingLinearLayout) container).getChildCount() > 0) {
             MessagingLinearLayout messagingContainer = (MessagingLinearLayout) container;
 
-            // Only consider the first visible child - transforming to a position other than the
-            // first looks bad because we have to move across other messages that are fading in.
             int childCount = messagingContainer.getChildCount();
             for (int i = 0; i < childCount; i++) {
                 View child = messagingContainer.getChildAt(i);
+
+                if (child.getVisibility() == View.GONE
+                        && child instanceof TextView
+                        && !TextUtils.isEmpty(((TextView) child).getText())) {
+                    mHistoricMessages.add(child);
+                }
+
+                // Only consider the first visible child - transforming to a position other than the
+                // first looks bad because we have to move across other messages that are fading in.
                 if (child.getId() == messagingContainer.getContractedChildId()) {
                     mContractedMessage = child;
                 } else if (child.getVisibility() == View.VISIBLE) {
@@ -75,4 +87,11 @@
                     mContractedMessage);
         }
     }
+
+    @Override
+    public void setRemoteInputVisible(boolean visible) {
+        for (int i = 0; i < mHistoricMessages.size(); i++) {
+            mHistoricMessages.get(i).setVisibility(visible ? View.VISIBLE : View.GONE);
+        }
+    }
 }
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 8106223..836482a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -19,12 +19,17 @@
 import android.animation.Animator;
 import android.animation.ValueAnimator;
 import android.content.Context;
+import android.graphics.Color;
 import android.graphics.ColorMatrix;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
 import android.service.notification.StatusBarNotification;
+import android.support.v4.graphics.ColorUtils;
 import android.view.NotificationHeaderView;
 import android.view.View;
 
 import com.android.systemui.Interpolators;
+import com.android.systemui.R;
 import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.TransformableView;
@@ -40,6 +45,8 @@
     protected final View mView;
     protected final ExpandableNotificationRow mRow;
     protected boolean mDark;
+    private int mBackgroundColor = 0;
+    protected boolean mShouldInvertDark;
     protected boolean mDarkInitialized = false;
 
     public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) {
@@ -85,7 +92,19 @@
      */
     public void notifyContentUpdated(StatusBarNotification notification, boolean isLowPriority) {
         mDarkInitialized = false;
-    };
+        Drawable background = mView.getBackground();
+        mBackgroundColor = 0;
+        if (background instanceof ColorDrawable) {
+            mBackgroundColor = ((ColorDrawable) background).getColor();
+            mView.setBackground(null);
+        }
+        mShouldInvertDark = mBackgroundColor == 0 || isColorLight(mBackgroundColor);
+    }
+
+    private boolean isColorLight(int backgroundColor) {
+        return Color.alpha(backgroundColor) == 0
+                || ColorUtils.calculateLuminance(backgroundColor) > 0.5;
+    }
 
 
     protected void startIntensityAnimation(ValueAnimator.AnimatorUpdateListener updateListener,
@@ -156,7 +175,8 @@
     }
 
     public int getCustomBackgroundColor() {
-        return 0;
+        // Parent notifications should always use the normal background color
+        return mRow.isSummaryWithChildren() ? 0 : mBackgroundColor;
     }
 
     public void setShowingLegacyBackground(boolean showing) {
@@ -164,4 +184,7 @@
 
     public void setContentHeight(int contentHeight, int minHeightHint) {
     }
+
+    public void setRemoteInputVisible(boolean visible) {
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
index 6b3d25d..d15ab10 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
@@ -18,10 +18,10 @@
 
 import android.util.ArraySet;
 import android.util.Pools;
-import android.view.NotificationHeaderView;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewParent;
+import android.view.animation.Interpolator;
 import android.widget.ImageView;
 import android.widget.ProgressBar;
 import android.widget.TextView;
@@ -38,10 +38,11 @@
 */
 public class TransformState {
 
+    public static final int TRANSFORM_X = 0x1;
+    public static final int TRANSFORM_Y = 0x10;
+    public static final int TRANSFORM_ALL = TRANSFORM_X | TRANSFORM_Y;
+
     private static final float UNDEFINED = -1f;
-    private static final int TRANSOFORM_X = 0x1;
-    private static final int TRANSOFORM_Y = 0x10;
-    private static final int TRANSOFORM_ALL = TRANSOFORM_X | TRANSOFORM_Y;
     private static final int CLIP_CLIPPING_SET = R.id.clip_children_set_tag;
     private static final int CLIP_CHILDREN_TAG = R.id.clip_children_tag;
     private static final int CLIP_TO_PADDING = R.id.clip_to_padding_tag;
@@ -80,25 +81,31 @@
     }
 
     public void transformViewFullyFrom(TransformState otherState, float transformationAmount) {
-        transformViewFrom(otherState, TRANSOFORM_ALL, null, transformationAmount);
+        transformViewFrom(otherState, TRANSFORM_ALL, null, transformationAmount);
+    }
+
+    public void transformViewFullyFrom(TransformState otherState,
+            ViewTransformationHelper.CustomTransformation customTransformation,
+            float transformationAmount) {
+        transformViewFrom(otherState, TRANSFORM_ALL, customTransformation, transformationAmount);
     }
 
     public void transformViewVerticalFrom(TransformState otherState,
             ViewTransformationHelper.CustomTransformation customTransformation,
             float transformationAmount) {
-        transformViewFrom(otherState, TRANSOFORM_Y, customTransformation, transformationAmount);
+        transformViewFrom(otherState, TRANSFORM_Y, customTransformation, transformationAmount);
     }
 
     public void transformViewVerticalFrom(TransformState otherState, float transformationAmount) {
-        transformViewFrom(otherState, TRANSOFORM_Y, null, transformationAmount);
+        transformViewFrom(otherState, TRANSFORM_Y, null, transformationAmount);
     }
 
     private void transformViewFrom(TransformState otherState, int transformationFlags,
             ViewTransformationHelper.CustomTransformation customTransformation,
             float transformationAmount) {
         final View transformedView = mTransformedView;
-        boolean transformX = (transformationFlags & TRANSOFORM_X) != 0;
-        boolean transformY = (transformationFlags & TRANSOFORM_Y) != 0;
+        boolean transformX = (transformationFlags & TRANSFORM_X) != 0;
+        boolean transformY = (transformationFlags & TRANSFORM_Y) != 0;
         boolean transformScale = transformScale();
         // lets animate the positions correctly
         if (transformationAmount == 0.0f
@@ -153,14 +160,30 @@
         float interpolatedValue = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(
                 transformationAmount);
         if (transformX) {
+            float interpolation = interpolatedValue;
+            if (customTransformation != null) {
+                Interpolator customInterpolator =
+                        customTransformation.getCustomInterpolator(TRANSFORM_X, true /* isFrom */);
+                if (customInterpolator != null) {
+                    interpolation = customInterpolator.getInterpolation(transformationAmount);
+                }
+            }
             transformedView.setTranslationX(NotificationUtils.interpolate(getTransformationStartX(),
                     0.0f,
-                    interpolatedValue));
+                    interpolation));
         }
         if (transformY) {
+            float interpolation = interpolatedValue;
+            if (customTransformation != null) {
+                Interpolator customInterpolator =
+                        customTransformation.getCustomInterpolator(TRANSFORM_Y, true /* isFrom */);
+                if (customInterpolator != null) {
+                    interpolation = customInterpolator.getInterpolation(transformationAmount);
+                }
+            }
             transformedView.setTranslationY(NotificationUtils.interpolate(getTransformationStartY(),
                     0.0f,
-                    interpolatedValue));
+                    interpolation));
         }
         if (transformScale) {
             float transformationStartScaleX = getTransformationStartScaleX();
@@ -207,17 +230,23 @@
     }
 
     public void transformViewFullyTo(TransformState otherState, float transformationAmount) {
-        transformViewTo(otherState, TRANSOFORM_ALL, null, transformationAmount);
+        transformViewTo(otherState, TRANSFORM_ALL, null, transformationAmount);
+    }
+
+    public void transformViewFullyTo(TransformState otherState,
+            ViewTransformationHelper.CustomTransformation customTransformation,
+            float transformationAmount) {
+        transformViewTo(otherState, TRANSFORM_ALL, customTransformation, transformationAmount);
     }
 
     public void transformViewVerticalTo(TransformState otherState,
             ViewTransformationHelper.CustomTransformation customTransformation,
             float transformationAmount) {
-        transformViewTo(otherState, TRANSOFORM_Y, customTransformation, transformationAmount);
+        transformViewTo(otherState, TRANSFORM_Y, customTransformation, transformationAmount);
     }
 
     public void transformViewVerticalTo(TransformState otherState, float transformationAmount) {
-        transformViewTo(otherState, TRANSOFORM_Y, null, transformationAmount);
+        transformViewTo(otherState, TRANSFORM_Y, null, transformationAmount);
     }
 
     private void transformViewTo(TransformState otherState, int transformationFlags,
@@ -226,8 +255,8 @@
         // lets animate the positions correctly
 
         final View transformedView = mTransformedView;
-        boolean transformX = (transformationFlags & TRANSOFORM_X) != 0;
-        boolean transformY = (transformationFlags & TRANSOFORM_Y) != 0;
+        boolean transformX = (transformationFlags & TRANSFORM_X) != 0;
+        boolean transformY = (transformationFlags & TRANSFORM_Y) != 0;
         boolean transformScale = transformScale();
         // lets animate the positions correctly
         if (transformationAmount == 0.0f) {
@@ -264,23 +293,37 @@
         int[] ownPosition = getLaidOutLocationOnScreen();
         if (transformX) {
             float endX = otherStablePosition[0] - ownPosition[0];
-            if (customTransformation != null
-                    && customTransformation.customTransformTarget(this, otherState)) {
-                endX = mTransformationEndX;
+            float interpolation = interpolatedValue;
+            if (customTransformation != null) {
+                if (customTransformation.customTransformTarget(this, otherState)) {
+                    endX = mTransformationEndX;
+                }
+                Interpolator customInterpolator =
+                        customTransformation.getCustomInterpolator(TRANSFORM_X, false /* isFrom */);
+                if (customInterpolator != null) {
+                    interpolation = customInterpolator.getInterpolation(transformationAmount);
+                }
             }
             transformedView.setTranslationX(NotificationUtils.interpolate(getTransformationStartX(),
                     endX,
-                    interpolatedValue));
+                    interpolation));
         }
         if (transformY) {
             float endY = otherStablePosition[1] - ownPosition[1];
-            if (customTransformation != null
-                    && customTransformation.customTransformTarget(this, otherState)) {
-                endY = mTransformationEndY;
+            float interpolation = interpolatedValue;
+            if (customTransformation != null) {
+                if (customTransformation.customTransformTarget(this, otherState)) {
+                    endY = mTransformationEndY;
+                }
+                Interpolator customInterpolator =
+                        customTransformation.getCustomInterpolator(TRANSFORM_Y, false /* isFrom */);
+                if (customInterpolator != null) {
+                    interpolation = customInterpolator.getInterpolation(transformationAmount);
+                }
             }
             transformedView.setTranslationY(NotificationUtils.interpolate(getTransformationStartY(),
                     endY,
-                    interpolatedValue));
+                    interpolation));
         }
         if (transformScale) {
             View otherView = otherState.getTransformedView();
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 42d9433..0773108 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
@@ -16,11 +16,7 @@
 
 package com.android.systemui.statusbar.phone;
 
-import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Build;
 import android.os.Handler;
 import android.os.PowerManager;
 import android.os.SystemClock;
@@ -98,7 +94,7 @@
     private DozeScrimController mDozeScrimController;
     private KeyguardViewMediator mKeyguardViewMediator;
     private ScrimController mScrimController;
-    private PhoneStatusBar mPhoneStatusBar;
+    private StatusBar mStatusBar;
     private final UnlockMethodCache mUnlockMethodCache;
     private final Context mContext;
     private boolean mGoingToSleep;
@@ -109,7 +105,7 @@
             DozeScrimController dozeScrimController,
             KeyguardViewMediator keyguardViewMediator,
             ScrimController scrimController,
-            PhoneStatusBar phoneStatusBar,
+            StatusBar statusBar,
             UnlockMethodCache unlockMethodCache) {
         mContext = context;
         mPowerManager = context.getSystemService(PowerManager.class);
@@ -119,7 +115,7 @@
         mDozeScrimController = dozeScrimController;
         mKeyguardViewMediator = keyguardViewMediator;
         mScrimController = scrimController;
-        mPhoneStatusBar = phoneStatusBar;
+        mStatusBar = statusBar;
         mUnlockMethodCache = unlockMethodCache;
     }
 
@@ -218,7 +214,7 @@
                 break;
             case MODE_WAKE_AND_UNLOCK_PULSING:
                 Trace.beginSection("MODE_WAKE_AND_UNLOCK_PULSING");
-                mPhoneStatusBar.updateMediaMetaData(false /* metaDataChanged */, 
+                mStatusBar.updateMediaMetaData(false /* metaDataChanged */,
                         true /* allowEnterAnimation */);
                 // Fall through.
                 Trace.endSection();
@@ -228,8 +224,8 @@
                 mDozeScrimController.abortPulsing();
                 mKeyguardViewMediator.onWakeAndUnlocking();
                 mScrimController.setWakeAndUnlocking();
-                if (mPhoneStatusBar.getNavigationBarView() != null) {
-                    mPhoneStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
+                if (mStatusBar.getNavigationBarView() != null) {
+                    mStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
                 }
                 Trace.endSection();
                 break;
@@ -240,7 +236,7 @@
         if (mMode != MODE_WAKE_AND_UNLOCK_PULSING) {
             mStatusBarWindowManager.setForceDozeBrightness(false);
         }
-        mPhoneStatusBar.notifyFpAuthModeChanged();
+        mStatusBar.notifyFpAuthModeChanged();
         Trace.endSection();
     }
 
@@ -309,7 +305,7 @@
         mMode = MODE_NONE;
         releaseFingerprintWakeLock();
         mStatusBarWindowManager.setForceDozeBrightness(false);
-        mPhoneStatusBar.notifyFpAuthModeChanged();
+        mStatusBar.notifyFpAuthModeChanged();
     }
 
     public void startKeyguardFadingAway() {
@@ -320,14 +316,14 @@
             public void run() {
                 mStatusBarWindowManager.setForceDozeBrightness(false);
             }
-        }, PhoneStatusBar.FADE_KEYGUARD_DURATION_PULSING);
+        }, StatusBar.FADE_KEYGUARD_DURATION_PULSING);
     }
 
     public void finishKeyguardFadingAway() {
         mMode = MODE_NONE;
-        if (mPhoneStatusBar.getNavigationBarView() != null) {
-            mPhoneStatusBar.getNavigationBarView().setWakeAndUnlocking(false);
+        if (mStatusBar.getNavigationBarView() != null) {
+            mStatusBar.getNavigationBarView().setWakeAndUnlocking(false);
         }
-        mPhoneStatusBar.notifyFpAuthModeChanged();
+        mStatusBar.notifyFpAuthModeChanged();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 79120d8..bfc0a80 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -19,6 +19,10 @@
 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
 import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 
+import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_LEFT_UNLOCK;
+import static com.android.systemui.tuner.LockscreenFragment.LOCKSCREEN_RIGHT_UNLOCK;
+import static com.android.systemui.tuner.LockscreenFragment.getIntentButton;
+
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.admin.DevicePolicyManager;
@@ -43,6 +47,7 @@
 import android.provider.MediaStore;
 import android.service.media.CameraPrewarmService;
 import android.telecom.TelecomManager;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.TypedValue;
@@ -74,6 +79,9 @@
 import com.android.systemui.statusbar.policy.AccessibilityController;
 import com.android.systemui.statusbar.policy.FlashlightController;
 import com.android.systemui.statusbar.policy.PreviewInflater;
+import com.android.systemui.tuner.LockscreenFragment;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
 
 /**
  * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status
@@ -81,9 +89,10 @@
  */
 public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener,
         UnlockMethodCache.OnUnlockMethodChangedListener,
-        AccessibilityController.AccessibilityStateChangedCallback, View.OnLongClickListener {
+        AccessibilityController.AccessibilityStateChangedCallback, View.OnLongClickListener,
+        Tunable {
 
-    final static String TAG = "PhoneStatusBar/KeyguardBottomAreaView";
+    final static String TAG = "StatusBar/KeyguardBottomAreaView";
 
     public static final String CAMERA_LAUNCH_SOURCE_AFFORDANCE = "lockscreen_affordance";
     public static final String CAMERA_LAUNCH_SOURCE_WIGGLE = "wiggle_gesture";
@@ -124,7 +133,7 @@
     private PreviewInflater mPreviewInflater;
     private KeyguardIndicationController mIndicationController;
     private AccessibilityController mAccessibilityController;
-    private PhoneStatusBar mPhoneStatusBar;
+    private StatusBar mStatusBar;
     private KeyguardAffordanceHelper mAffordanceHelper;
 
     private boolean mUserSetupComplete;
@@ -148,7 +157,13 @@
     private Drawable mLeftAssistIcon;
 
     private IntentButton mRightButton = new DefaultRightButton();
+    private IntentButton mRightDefault = mRightButton;
+    private IntentButton mRightPlugin;
+    private String mRightButtonStr;
     private IntentButton mLeftButton = new DefaultLeftButton();
+    private IntentButton mLeftDefault = mLeftButton;
+    private IntentButton mLeftPlugin;
+    private String mLeftButtonStr;
 
     public KeyguardBottomAreaView(Context context) {
         this(context, null);
@@ -190,7 +205,7 @@
         public boolean performAccessibilityAction(View host, int action, Bundle args) {
             if (action == ACTION_CLICK) {
                 if (host == mLockIcon) {
-                    mPhoneStatusBar.animateCollapsePanels(
+                    mStatusBar.animateCollapsePanels(
                             CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
                     return true;
                 } else if (host == mRightAffordanceView) {
@@ -241,17 +256,22 @@
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
+        mAccessibilityController.addStateChangedCallback(this);
         PluginManager.getInstance(getContext()).addPluginListener(RIGHT_BUTTON_PLUGIN,
                 mRightListener, IntentButtonProvider.VERSION, false /* Only allow one */);
         PluginManager.getInstance(getContext()).addPluginListener(LEFT_BUTTON_PLUGIN,
                 mLeftListener, IntentButtonProvider.VERSION, false /* Only allow one */);
+        TunerService.get(getContext()).addTunable(this, LockscreenFragment.LOCKSCREEN_LEFT_BUTTON,
+                LockscreenFragment.LOCKSCREEN_RIGHT_BUTTON);
     }
 
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
+        mAccessibilityController.removeStateChangedCallback(this);
         PluginManager.getInstance(getContext()).removePluginListener(mRightListener);
         PluginManager.getInstance(getContext()).removePluginListener(mLeftListener);
+        TunerService.get(getContext()).removeTunable(this);
     }
 
     private void initAccessibility() {
@@ -305,8 +325,8 @@
         mRightAffordanceView.setContentDescription(state.contentDescription);
     }
 
-    public void setPhoneStatusBar(PhoneStatusBar phoneStatusBar) {
-        mPhoneStatusBar = phoneStatusBar;
+    public void setStatusBar(StatusBar statusBar) {
+        mStatusBar = statusBar;
         updateCameraVisibility(); // in case onFinishInflate() was called too early
     }
 
@@ -370,13 +390,13 @@
     private boolean isCameraDisabledByDpm() {
         final DevicePolicyManager dpm =
                 (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
-        if (dpm != null && mPhoneStatusBar != null) {
+        if (dpm != null && mStatusBar != null) {
             try {
                 final int userId = ActivityManager.getService().getCurrentUser().id;
                 final int disabledFlags = dpm.getKeyguardDisabledFeatures(null, userId);
                 final  boolean disabledBecauseKeyguardSecure =
                         (disabledFlags & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0
-                                && mPhoneStatusBar.isKeyguardSecure();
+                                && mStatusBar.isKeyguardSecure();
                 return dpm.getCameraDisabled(null) || disabledBecauseKeyguardSecure;
             } catch (RemoteException e) {
                 Log.e(TAG, "Can't get userId", e);
@@ -412,7 +432,7 @@
             if (!mAccessibilityController.isAccessibilityEnabled()) {
                 handleTrustCircleClick();
             } else {
-                mPhoneStatusBar.animateCollapsePanels(
+                mStatusBar.animateCollapsePanels(
                         CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
             }
         }
@@ -549,11 +569,13 @@
                 mAssistManager.launchVoiceAssistFromKeyguard();
             }
         };
-        if (mPhoneStatusBar.isKeyguardCurrentlySecure()) {
+        if (mStatusBar.isKeyguardCurrentlySecure()) {
             AsyncTask.execute(runnable);
         } else {
-            mPhoneStatusBar.executeRunnableDismissingKeyguard(runnable, null /* cancelAction */,
-                    false /* dismissShade */, false /* afterKeyguardGone */, true /* deferred */);
+            boolean dismissShade = !TextUtils.isEmpty(mRightButtonStr)
+                    && TunerService.get(getContext()).getValue(LOCKSCREEN_RIGHT_UNLOCK, 1) != 0;
+            mStatusBar.executeRunnableDismissingKeyguard(runnable, null /* cancelAction */,
+                    dismissShade, false /* afterKeyguardGone */, true /* deferred */);
         }
     }
 
@@ -571,7 +593,9 @@
                 }
             });
         } else {
-            mActivityStarter.startActivity(mLeftButton.getIntent(), false /* dismissShade */);
+            boolean dismissShade = !TextUtils.isEmpty(mLeftButtonStr)
+                    && TunerService.get(getContext()).getValue(LOCKSCREEN_LEFT_UNLOCK, 1) != 0;
+            mActivityStarter.startActivity(mLeftButton.getIntent(), dismissShade);
         }
     }
 
@@ -763,15 +787,33 @@
         inflateCameraPreview();
     }
 
+    @Override
+    public void onTuningChanged(String key, String newValue) {
+        if (LockscreenFragment.LOCKSCREEN_LEFT_BUTTON.equals(key)) {
+            mLeftButtonStr = newValue;
+            mLeftIsVoiceAssist = TextUtils.isEmpty(mLeftButtonStr) && mLeftPlugin == null;
+            mLeftButton = getIntentButton(mContext, mLeftButtonStr, mLeftPlugin, mLeftDefault);
+            updateLeftAffordance();
+        } else {
+            mRightButtonStr = newValue;
+            mRightButton = getIntentButton(mContext, mRightButtonStr, mRightPlugin, mRightDefault);
+            updateRightAffordanceIcon();
+            updateCameraVisibility();
+            inflateCameraPreview();
+        }
+    }
+
     private void setRightButton(IntentButton button) {
-        mRightButton = button;
+        mRightPlugin = button;
+        mRightButton = getIntentButton(mContext, mRightButtonStr, mRightPlugin, mRightDefault);
         updateRightAffordanceIcon();
         updateCameraVisibility();
         inflateCameraPreview();
     }
 
     private void setLeftButton(IntentButton button) {
-        mLeftButton = button;
+        mLeftPlugin = button;
+        mLeftButton = getIntentButton(mContext, mLeftButtonStr, mLeftPlugin, mLeftDefault);
         mLeftIsVoiceAssist = false;
         updateLeftAffordance();
     }
@@ -785,7 +827,7 @@
 
         @Override
         public void onPluginDisconnected(IntentButtonProvider plugin) {
-            setRightButton(new DefaultRightButton());
+            setRightButton(null);
         }
     };
 
@@ -798,7 +840,7 @@
 
         @Override
         public void onPluginDisconnected(IntentButtonProvider plugin) {
-            setLeftButton(new DefaultLeftButton());
+            setLeftButton(null);
         }
     };
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
index af6e259..99b3aa8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -51,7 +51,7 @@
 
     private static final String TAG = "LockscreenWallpaper";
 
-    private final PhoneStatusBar mBar;
+    private final StatusBar mBar;
     private final WallpaperManager mWallpaperManager;
     private final Handler mH;
     private final KeyguardUpdateMonitor mUpdateMonitor;
@@ -64,7 +64,7 @@
     private UserHandle mSelectedUser;
     private AsyncTask<Void, Void, LoaderResult> mLoader;
 
-    public LockscreenWallpaper(Context ctx, PhoneStatusBar bar, Handler h) {
+    public LockscreenWallpaper(Context ctx, StatusBar bar, Handler h) {
         mBar = bar;
         mH = h;
         mWallpaperManager = (WallpaperManager) ctx.getSystemService(Context.WALLPAPER_SERVICE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index d40326a..62b536e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -20,8 +20,8 @@
 import static android.app.StatusBarManager.windowStateToString;
 
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
-import static com.android.systemui.statusbar.phone.PhoneStatusBar.DEBUG_WINDOW_STATE;
-import static com.android.systemui.statusbar.phone.PhoneStatusBar.dumpBarTransitions;
+import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_WINDOW_STATE;
+import static com.android.systemui.statusbar.phone.StatusBar.dumpBarTransitions;
 
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -67,7 +67,6 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
-import com.android.systemui.SystemUIApplication;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
@@ -105,7 +104,7 @@
     protected AccessibilityManager mAccessibilityManager;
 
     private int mDisabledFlags1;
-    private PhoneStatusBar mPhoneStatusBar;
+    private StatusBar mStatusBar;
     private Recents mRecents;
     private Divider mDivider;
     private WindowManager mWindowManager;
@@ -128,7 +127,7 @@
         super.onCreate(savedInstanceState);
         mCommandQueue = SysUiServiceProvider.getComponent(getContext(), CommandQueue.class);
         mCommandQueue.addCallbacks(this);
-        mPhoneStatusBar = SysUiServiceProvider.getComponent(getContext(), PhoneStatusBar.class);
+        mStatusBar = SysUiServiceProvider.getComponent(getContext(), StatusBar.class);
         mRecents = SysUiServiceProvider.getComponent(getContext(), Recents.class);
         mDivider = SysUiServiceProvider.getComponent(getContext(), Divider.class);
         mWindowManager = getContext().getSystemService(WindowManager.class);
@@ -262,7 +261,7 @@
         if (mNavigationBarView != null) {
             mNavigationBarView.setNavigationIconHints(hints);
         }
-        mPhoneStatusBar.checkBarModes();
+        mStatusBar.checkBarModes();
     }
 
     @Override
@@ -300,21 +299,21 @@
 
     /**
      * Calls appTransitionStarting for the nav bar regardless of whether keyguard is going away.
-     * public so PhoneStatusBar can force this when needed.
+     * public so StatusBar can force this when needed.
      */
     public void doAppTransitionStarting(long startTime, long duration) {
         mNavigationBarView.getLightTransitionsController().appTransitionStarting(startTime,
                 duration);
     }
 
-    // Injected from PhoneStatusBar at creation.
+    // Injected from StatusBar at creation.
     public void setCurrentSysuiVisibility(int systemUiVisibility) {
         mSystemUiVisibility = systemUiVisibility;
-        mNavigationBarMode = mPhoneStatusBar.computeBarMode(0, mSystemUiVisibility,
+        mNavigationBarMode = mStatusBar.computeBarMode(0, mSystemUiVisibility,
                 View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT,
                 View.NAVIGATION_BAR_TRANSPARENT);
         checkNavBarModes();
-        mPhoneStatusBar.touchAutoHide();
+        mStatusBar.touchAutoHide();
         mLightBarController.onNavigationVisibilityChanged(mSystemUiVisibility, 0 /* mask */,
                 true /* nbModeChanged */, mNavigationBarMode);
     }
@@ -331,7 +330,7 @@
 
             // update navigation bar mode
             final int nbMode = getView() == null
-                    ? -1 : mPhoneStatusBar.computeBarMode(oldVal, newVal,
+                    ? -1 : mStatusBar.computeBarMode(oldVal, newVal,
                     View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT,
                     View.NAVIGATION_BAR_TRANSPARENT);
             nbModeChanged = nbMode != -1;
@@ -340,7 +339,7 @@
                     mNavigationBarMode = nbMode;
                     checkNavBarModes();
                 }
-                mPhoneStatusBar.touchAutoHide();
+                mStatusBar.touchAutoHide();
             }
         }
 
@@ -370,7 +369,7 @@
     }
 
     private boolean shouldDisableNavbarGestures() {
-        return !mPhoneStatusBar.isDeviceProvisioned()
+        return !mStatusBar.isDeviceProvisioned()
                 || (mDisabledFlags1 & StatusBarManager.DISABLE_SEARCH) != 0;
     }
 
@@ -418,7 +417,7 @@
                 TelecomManager telecomManager =
                         getContext().getSystemService(TelecomManager.class);
                 if (telecomManager != null && telecomManager.isRinging()) {
-                    if (mPhoneStatusBar.isKeyguardShowing()) {
+                    if (mStatusBar.isKeyguardShowing()) {
                         Log.i(TAG, "Ignoring HOME; there's a ringing incoming call. " +
                                 "No heads up");
                         mHomeBlockedThisTouch = true;
@@ -428,18 +427,18 @@
                 break;
             case MotionEvent.ACTION_UP:
             case MotionEvent.ACTION_CANCEL:
-                mPhoneStatusBar.awakenDreams();
+                mStatusBar.awakenDreams();
                 break;
         }
         return false;
     }
 
     private void onVerticalChanged(boolean isVertical) {
-        mPhoneStatusBar.setQsScrimEnabled(!isVertical);
+        mStatusBar.setQsScrimEnabled(!isVertical);
     }
 
     private boolean onNavigationTouch(View v, MotionEvent event) {
-        mPhoneStatusBar.checkUserAutohide(v, event);
+        mStatusBar.checkUserAutohide(v, event);
         return false;
     }
 
@@ -450,7 +449,7 @@
         }
         MetricsLogger.action(getContext(), MetricsEvent.ACTION_ASSIST_LONG_PRESS);
         mAssistManager.startAssist(new Bundle() /* args */);
-        mPhoneStatusBar.awakenDreams();
+        mStatusBar.awakenDreams();
         if (mNavigationBarView != null) {
             mNavigationBarView.abortCurrentGesture();
         }
@@ -478,7 +477,7 @@
             LatencyTracker.getInstance(getContext()).onActionStart(
                     LatencyTracker.ACTION_TOGGLE_RECENTS);
         }
-        mPhoneStatusBar.awakenDreams();
+        mStatusBar.awakenDreams();
         mCommandQueue.toggleRecentApps();
     }
 
@@ -550,11 +549,11 @@
             return false;
         }
 
-        return mPhoneStatusBar.toggleSplitScreenMode(MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS,
+        return mStatusBar.toggleSplitScreenMode(MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS,
                 MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS);
     }
 
-    // ----- Methods that PhoneStatusBar talks to (should be minimized) -----
+    // ----- Methods that StatusBar talks to (should be minimized) -----
 
     public void setLightBarController(LightBarController lightBarController) {
         mLightBarController = lightBarController;
@@ -584,7 +583,7 @@
     }
 
     public void checkNavBarModes() {
-        mPhoneStatusBar.checkBarMode(mNavigationBarMode,
+        mStatusBar.checkBarMode(mNavigationBarMode,
                 mNavigationBarWindowState, mNavigationBarView.getBarTransitions());
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index f04a9ee..9b4867e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -17,6 +17,7 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.graphics.drawable.Icon;
 import android.util.AttributeSet;
 import android.util.SparseArray;
 import android.view.Display;
@@ -47,6 +48,8 @@
     private static final String TAG = "NavBarInflater";
 
     public static final String NAV_BAR_VIEWS = "sysui_nav_bar";
+    public static final String NAV_BAR_LEFT = "sysui_nav_bar_left";
+    public static final String NAV_BAR_RIGHT = "sysui_nav_bar_right";
 
     public static final String MENU_IME = "menu_ime";
     public static final String BACK = "back";
@@ -55,6 +58,8 @@
     public static final String NAVSPACE = "space";
     public static final String CLIPBOARD = "clipboard";
     public static final String KEY = "key";
+    public static final String LEFT = "left";
+    public static final String RIGHT = "right";
 
     public static final String GRAVITY_SEPARATOR = ";";
     public static final String BUTTON_SEPARATOR = ",";
@@ -130,7 +135,8 @@
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
-        TunerService.get(getContext()).addTunable(this, NAV_BAR_VIEWS);
+        TunerService.get(getContext()).addTunable(this, NAV_BAR_VIEWS, NAV_BAR_LEFT,
+                NAV_BAR_RIGHT);
         PluginManager.getInstance(getContext()).addPluginListener(NavBarButtonProvider.ACTION, this,
                 NavBarButtonProvider.VERSION, true /* Allow multiple */);
     }
@@ -148,6 +154,9 @@
                 clearViews();
                 inflateLayout(newValue);
             }
+        } else if (NAV_BAR_LEFT.equals(key) || NAV_BAR_RIGHT.equals(key)) {
+            clearViews();
+            inflateLayout(mCurrentLayout);
         }
     }
 
@@ -268,6 +277,13 @@
             boolean landscape) {
         View v = null;
         String button = extractButton(buttonSpec);
+        if (LEFT.equals(button)) {
+            buttonSpec = TunerService.get(mContext).getValue(NAV_BAR_LEFT, NAVSPACE);
+            button = extractButton(buttonSpec);
+        } else if (RIGHT.equals(button)) {
+            buttonSpec = TunerService.get(mContext).getValue(NAV_BAR_RIGHT, MENU_IME);
+            button = extractButton(buttonSpec);
+        }
         // Let plugins go first so they can override a standard view if they want.
         for (NavBarButtonProvider provider : mPlugins) {
             v = provider.createView(buttonSpec, parent);
@@ -291,7 +307,14 @@
             v = inflater.inflate(R.layout.custom_key, parent, false);
             ((KeyButtonView) v).setCode(code);
             if (uri != null) {
-                ((KeyButtonView) v).loadAsync(uri);
+                if (uri.contains(":")) {
+                    ((KeyButtonView) v).loadAsync(Icon.createWithContentUri(uri));
+                } else if (uri.contains("/")) {
+                    int index = uri.indexOf('/');
+                    String pkg = uri.substring(0, index);
+                    int id = Integer.parseInt(uri.substring(index + 1));
+                    ((KeyButtonView) v).loadAsync(Icon.createWithResource(pkg, id));
+                }
             }
         }
         return v;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 319f124..5e988fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -28,7 +28,6 @@
 import android.content.res.Configuration;
 import android.graphics.Point;
 import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.os.Message;
 import android.os.RemoteException;
@@ -53,7 +52,6 @@
 import com.android.systemui.plugins.PluginManager;
 import com.android.systemui.plugins.statusbar.phone.NavGesture;
 import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
-import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.policy.DeadZone;
 import com.android.systemui.statusbar.policy.KeyButtonDrawable;
@@ -553,8 +551,8 @@
                 }
 
                 @Override
-                public void onDockedStackMinimizedChanged(boolean minimized, long animDuration)
-                        throws RemoteException {
+                public void onDockedStackMinimizedChanged(boolean minimized, long animDuration,
+                        boolean isHomeStackResizable) throws RemoteException {
                 }
 
                 @Override
@@ -784,7 +782,7 @@
         final Point size = new Point();
         mDisplay.getRealSize(size);
 
-        pw.println(String.format("      this: " + PhoneStatusBar.viewInfo(this)
+        pw.println(String.format("      this: " + StatusBar.viewInfo(this)
                         + " " + visibilityToString(getVisibility())));
 
         getWindowVisibleDisplayFrame(r);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 32b9969..0386398 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -33,7 +33,7 @@
     private int mIconHPadding;
     private int mIconTint = Color.WHITE;
 
-    private PhoneStatusBar mPhoneStatusBar;
+    private StatusBar mStatusBar;
     protected View mNotificationIconArea;
     private NotificationIconContainer mNotificationIcons;
     private NotificationIconContainer mShelfIcons;
@@ -41,8 +41,8 @@
     private NotificationStackScrollLayout mNotificationScrollLayout;
     private Context mContext;
 
-    public NotificationIconAreaController(Context context, PhoneStatusBar phoneStatusBar) {
-        mPhoneStatusBar = phoneStatusBar;
+    public NotificationIconAreaController(Context context, StatusBar statusBar) {
+        mStatusBar = statusBar;
         mNotificationColorUtil = NotificationColorUtil.getInstance(context);
         mContext = context;
 
@@ -64,11 +64,11 @@
         mNotificationIcons = (NotificationIconContainer) mNotificationIconArea.findViewById(
                 R.id.notificationIcons);
 
-        NotificationShelf shelf = mPhoneStatusBar.getNotificationShelf();
+        NotificationShelf shelf = mStatusBar.getNotificationShelf();
         mShelfIcons = shelf.getShelfIcons();
         shelf.setCollapsedIcons(mNotificationIcons);
 
-        mNotificationScrollLayout = mPhoneStatusBar.getNotificationScrollLayout();
+        mNotificationScrollLayout = mStatusBar.getNotificationScrollLayout();
     }
 
     public void onDensityOrFontScaleChanged(Context context) {
@@ -124,7 +124,7 @@
     }
 
     protected int getHeight() {
-        return mPhoneStatusBar.getStatusBarHeight();
+        return mStatusBar.getStatusBarHeight();
     }
 
     protected boolean shouldShowNotificationIcon(NotificationData.Entry entry,
@@ -133,7 +133,7 @@
                 && !NotificationData.showNotificationEvenIfUnprovisioned(entry.notification)) {
             return false;
         }
-        if (!PhoneStatusBar.isTopLevelChild(entry)) {
+        if (!StatusBar.isTopLevelChild(entry)) {
             return false;
         }
         if (entry.row.getVisibility() == View.GONE) {
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 3bdd5e5..fe7e915 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -92,7 +92,7 @@
 
     public static final long DOZE_ANIMATION_DURATION = 700;
 
-    private KeyguardAffordanceHelper mAfforanceHelper;
+    private KeyguardAffordanceHelper mAffordanceHelper;
     private KeyguardUserSwitcher mKeyguardUserSwitcher;
     private KeyguardStatusBarView mKeyguardStatusBar;
     private QS mQs;
@@ -219,7 +219,7 @@
         mFalsingManager = FalsingManager.getInstance(context);
     }
 
-    public void setStatusBar(PhoneStatusBar bar) {
+    public void setStatusBar(StatusBar bar) {
         mStatusBar = bar;
     }
 
@@ -239,8 +239,8 @@
         mNotificationStackScroller.setOnEmptySpaceClickListener(this);
         mKeyguardBottomArea = (KeyguardBottomAreaView) findViewById(R.id.keyguard_bottom_area);
         mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim);
-        mAfforanceHelper = new KeyguardAffordanceHelper(this, getContext());
-        mKeyguardBottomArea.setAffordanceHelper(mAfforanceHelper);
+        mAffordanceHelper = new KeyguardAffordanceHelper(this, getContext());
+        mKeyguardBottomArea.setAffordanceHelper(mAffordanceHelper);
         mLastOrientation = getResources().getConfiguration().orientation;
 
         mQsFrame = (FrameLayout) findViewById(R.id.qs_frame);
@@ -516,7 +516,7 @@
         mBlockTouches = false;
         mUnlockIconActive = false;
         if (!mLaunchingAffordance) {
-            mAfforanceHelper.reset(false);
+            mAffordanceHelper.reset(false);
             mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
         }
         closeQs();
@@ -762,8 +762,9 @@
         }
         if ((!mIsExpanding || mHintAnimationRunning)
                 && !mQsExpanded
-                && mStatusBar.getBarState() != StatusBarState.SHADE) {
-            mAfforanceHelper.onTouchEvent(event);
+                && mStatusBar.getBarState() != StatusBarState.SHADE
+                && !mDozing) {
+            mAffordanceHelper.onTouchEvent(event);
         }
         if (mOnlyAffordanceInThisMotion) {
             return true;
@@ -881,7 +882,7 @@
 
     @Override
     protected boolean shouldGestureIgnoreXTouchSlop(float x, float y) {
-        return !mAfforanceHelper.isOnAffordanceIcon(x, y);
+        return !mAffordanceHelper.isOnAffordanceIcon(x, y);
     }
 
     private void onQsTouch(MotionEvent event) {
@@ -1722,7 +1723,7 @@
         }
         if (mStatusBar.getBarState() == StatusBarState.KEYGUARD
                 || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED) {
-            mAfforanceHelper.animateHideLeftRightIcon();
+            mAffordanceHelper.animateHideLeftRightIcon();
         }
         mNotificationStackScroller.onPanelTrackingStarted();
     }
@@ -1739,7 +1740,7 @@
         if (expand && (mStatusBar.getBarState() == StatusBarState.KEYGUARD
                 || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED)) {
             if (!mHintAnimationRunning) {
-                mAfforanceHelper.reset(true);
+                mAffordanceHelper.reset(true);
             }
         }
         if (!expand && (mStatusBar.getBarState() == StatusBarState.KEYGUARD
@@ -1785,7 +1786,7 @@
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        mAfforanceHelper.onConfigurationChanged();
+        mAffordanceHelper.onConfigurationChanged();
         if (newConfig.orientation != mLastOrientation) {
             resetVerticalPanelPosition();
         }
@@ -1806,7 +1807,7 @@
     @Override
     public void onRtlPropertiesChanged(int layoutDirection) {
         if (layoutDirection != mOldLayoutDirection) {
-            mAfforanceHelper.onRtlPropertiesChanged();
+            mAffordanceHelper.onRtlPropertiesChanged();
             mOldLayoutDirection = layoutDirection;
         }
     }
@@ -1938,7 +1939,7 @@
             return;
         }
         mHintAnimationRunning = true;
-        mAfforanceHelper.startHintAnimation(rightIcon, new Runnable() {
+        mAffordanceHelper.startHintAnimation(rightIcon, new Runnable() {
             @Override
             public void run() {
                 mHintAnimationRunning = false;
@@ -2351,7 +2352,7 @@
         } else {
             animate = false;
         }
-        mAfforanceHelper.launchAffordance(animate, getLayoutDirection() == LAYOUT_DIRECTION_RTL);
+        mAffordanceHelper.launchAffordance(animate, getLayoutDirection() == LAYOUT_DIRECTION_RTL);
     }
 
     public void onAffordanceLaunchEnded() {
@@ -2397,7 +2398,7 @@
                 ? null : resolveInfo.activityInfo.packageName;
         return packageToLaunch != null &&
                (keyguardIsShowing || !isForegroundApp(packageToLaunch)) &&
-               !mAfforanceHelper.isSwipingInProgress();
+               !mAffordanceHelper.isSwipingInProgress();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 18e394e..5f67468 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -60,7 +60,7 @@
         Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
     }
 
-    protected PhoneStatusBar mStatusBar;
+    protected StatusBar mStatusBar;
     protected HeadsUpManager mHeadsUpManager;
 
     private float mPeekHeight;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index c80b3ad..7e08812 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -30,10 +30,10 @@
 
 public class PhoneStatusBarView extends PanelBar {
     private static final String TAG = "PhoneStatusBarView";
-    private static final boolean DEBUG = PhoneStatusBar.DEBUG;
+    private static final boolean DEBUG = StatusBar.DEBUG;
     private static final boolean DEBUG_GESTURES = false;
 
-    PhoneStatusBar mBar;
+    StatusBar mBar;
 
     boolean mIsFullyOpenedPanel = false;
     private final PhoneStatusBarTransitions mBarTransitions;
@@ -59,7 +59,7 @@
         return mBarTransitions;
     }
 
-    public void setBar(PhoneStatusBar bar) {
+    public void setBar(StatusBar bar) {
         mBar = bar;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 2f76cb1..dd567e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -71,7 +71,7 @@
     public static final String TILES_SETTING = Secure.QS_TILES;
 
     private final Context mContext;
-    private final PhoneStatusBar mStatusBar;
+    private final StatusBar mStatusBar;
     private final LinkedHashMap<String, QSTile<?>> mTiles = new LinkedHashMap<>();
     protected final ArrayList<String> mTileSpecs = new ArrayList<>();
     private final TileServices mServices;
@@ -81,7 +81,7 @@
     private final StatusBarIconController mIconController;
     private int mCurrentUser;
 
-    public QSTileHost(Context context, PhoneStatusBar statusBar,
+    public QSTileHost(Context context, StatusBar statusBar,
             StatusBarIconController iconController) {
         mIconController = iconController;
         mContext = context;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index 5536209..c0e9653 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -29,6 +29,7 @@
 import android.os.UserManager;
 import android.support.annotation.VisibleForTesting;
 import android.util.AttributeSet;
+import android.util.SparseBooleanArray;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
@@ -55,6 +56,8 @@
 import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
+import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
 import com.android.systemui.statusbar.policy.UserInfoController;
@@ -63,7 +66,7 @@
 
 public class QuickStatusBarHeader extends BaseStatusBarHeader implements
         NextAlarmChangeCallback, OnClickListener, OnUserInfoChangedListener, EmergencyListener,
-        BatteryStateChangeCallback {
+        BatteryStateChangeCallback, SignalCallback {
 
     private static final String TAG = "QuickStatusBarHeader";
 
@@ -106,6 +109,8 @@
     private boolean mShowFullAlarm;
     private float mDateTimeTranslation;
     private TextView mBatteryLevel;
+    private SparseBooleanArray mRoamingsBySubId = new SparseBooleanArray();
+    private boolean mIsRoaming;
 
     public QuickStatusBarHeader(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -300,7 +305,7 @@
     protected void updateVisibilities() {
         updateAlarmVisibilities();
         updateDateTimePosition();
-        mEmergencyOnly.setVisibility(mExpanded && mShowEmergencyCallsOnly
+        mEmergencyOnly.setVisibility(mExpanded && (mShowEmergencyCallsOnly || mIsRoaming)
                 ? View.VISIBLE : View.INVISIBLE);
         mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility(
                 TunerService.isTunerEnabled(mContext) ? View.VISIBLE : View.INVISIBLE);
@@ -311,7 +316,7 @@
     }
 
     private void updateDateTimePosition() {
-        mDateTimeAlarmGroup.setTranslationY(mShowEmergencyCallsOnly
+        mDateTimeAlarmGroup.setTranslationY(mShowEmergencyCallsOnly || mIsRoaming
                 ? mExpansionAmount * mDateTimeTranslation : 0);
     }
 
@@ -321,11 +326,13 @@
             mUserInfoController.addCallback(this);
             if (Dependency.get(NetworkController.class).hasVoiceCallingFeature()) {
                 Dependency.get(NetworkController.class).addEmergencyListener(this);
+                Dependency.get(NetworkController.class).addCallback(this);
             }
         } else {
             mNextAlarmController.removeCallback(this);
             mUserInfoController.removeCallback(this);
             Dependency.get(NetworkController.class).removeEmergencyListener(this);
+            Dependency.get(NetworkController.class).removeCallback(this);
         }
     }
 
@@ -406,6 +413,28 @@
         // Don't care.
     }
 
+    public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
+            int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
+            String description, boolean isWide, int subId, boolean roaming) {
+        mRoamingsBySubId.put(subId, roaming);
+        boolean isRoaming = calculateRoaming();
+        if (mIsRoaming != isRoaming) {
+            mIsRoaming = isRoaming;
+            mEmergencyOnly.setText(mIsRoaming ? R.string.accessibility_data_connection_roaming
+                    : com.android.internal.R.string.emergency_calls_only);
+            if (mExpanded) {
+                updateEverything();
+            }
+        }
+    }
+
+    private boolean calculateRoaming() {
+        for (int i = 0; i < mRoamingsBySubId.size(); i++) {
+            if (mRoamingsBySubId.valueAt(i)) return true;
+        }
+        return false;
+    }
+
     @Override
     public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
         mMultiUserAvatar.setImageDrawable(picture);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
similarity index 65%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 8dcc693..018d888 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -72,9 +72,7 @@
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
-import android.os.HandlerThread;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.RemoteException;
@@ -127,8 +125,6 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
-import com.android.systemui.SysUiServiceProvider;
-import com.android.systemui.SystemUIApplication;
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.classifier.FalsingLog;
@@ -141,6 +137,8 @@
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.ActivityStarter;
 import com.android.systemui.plugins.qs.QS.BaseStatusBarHeader;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.SnoozeListener;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.SnoozeOption;
 import com.android.systemui.qs.QSFragment;
 import com.android.systemui.qs.QSPanel;
 import com.android.systemui.recents.ScreenPinningRequest;
@@ -151,7 +149,6 @@
 import com.android.systemui.stackdivider.WindowManagerProxy;
 import com.android.systemui.statusbar.ActivatableNotificationView;
 import com.android.systemui.statusbar.BackDropView;
-import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.DismissView;
 import com.android.systemui.statusbar.DragDownHelper;
@@ -160,9 +157,13 @@
 import com.android.systemui.statusbar.GestureRecorder;
 import com.android.systemui.statusbar.KeyboardShortcuts;
 import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.NotificationContentView;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.NotificationData.Entry;
+import com.android.systemui.statusbar.NotificationGuts;
+import com.android.systemui.statusbar.NotificationInfo;
 import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.NotificationSnooze;
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.ScrimView;
 import com.android.systemui.statusbar.SignalClusterView;
@@ -171,7 +172,6 @@
 import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
-import com.android.systemui.statusbar.policy.BatteryControllerImpl;
 import com.android.systemui.statusbar.policy.BrightnessMirrorController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
@@ -183,11 +183,9 @@
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
 import com.android.systemui.statusbar.policy.PreviewInflater;
-import com.android.systemui.statusbar.policy.SecurityController;
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.statusbar.policy.ZenModeController;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
 
@@ -197,17 +195,102 @@
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.GregorianCalendar;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
+import android.app.ActivityManager.StackId;
+import android.app.INotificationManager;
+import android.app.KeyguardManager;
+import android.app.NotificationChannel;
+import android.app.RemoteInput;
+import android.app.TaskStackBuilder;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
+import android.os.Build;
+import android.os.Handler;
+import android.service.dreams.DreamService;
+import android.service.dreams.IDreamManager;
+import android.service.notification.NotificationListenerService;
+import android.service.vr.IVrManager;
+import android.service.vr.IVrStateCallbacks;
+import android.text.TextUtils;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseBooleanArray;
+import android.view.IWindowManager;
+import android.view.ViewAnimationUtils;
+import android.view.accessibility.AccessibilityManager;
+import android.widget.RemoteViews;
+import android.widget.Toast;
+
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.DejankUtils;
+import com.android.systemui.RecentsComponent;
+import com.android.systemui.SwipeHelper;
+import com.android.systemui.SystemUI;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.MenuItem;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.SnoozeGutsContent;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.statusbar.policy.RemoteInputView;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
+import com.android.systemui.util.NotificationChannels;
+
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+import java.util.Stack;
+
+public class StatusBar extends SystemUI implements DemoMode,
         DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener,
-        OnHeadsUpChangedListener, VisualStabilityManager.Callback {
-    static final String TAG = "PhoneStatusBar";
-    public static final boolean DEBUG = BaseStatusBar.DEBUG;
+        OnHeadsUpChangedListener, VisualStabilityManager.Callback, SnoozeListener,
+        CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
+        ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment,
+        ExpandableNotificationRow.OnExpandClickListener {
+    public static final boolean MULTIUSER_DEBUG = false;
+
+    public static final boolean ENABLE_REMOTE_INPUT =
+            SystemProperties.getBoolean("debug.enable_remote_input", true);
+    public static final boolean ENABLE_CHILD_NOTIFICATIONS
+            = SystemProperties.getBoolean("debug.child_notifs", true);
+    public static final boolean FORCE_REMOTE_INPUT_HISTORY =
+            SystemProperties.getBoolean("debug.force_remoteinput_history", false);
+    private static boolean ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT = false;
+
+    protected static final int MSG_SHOW_RECENT_APPS = 1019;
+    protected static final int MSG_HIDE_RECENT_APPS = 1020;
+    protected static final int MSG_TOGGLE_RECENTS_APPS = 1021;
+    protected static final int MSG_PRELOAD_RECENT_APPS = 1022;
+    protected static final int MSG_CANCEL_PRELOAD_RECENT_APPS = 1023;
+    protected static final int MSG_SHOW_NEXT_AFFILIATED_TASK = 1024;
+    protected static final int MSG_SHOW_PREV_AFFILIATED_TASK = 1025;
+    protected static final int MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU = 1026;
+    protected static final int MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU = 1027;
+
+    protected static final boolean ENABLE_HEADS_UP = true;
+    protected static final String SETTING_HEADS_UP_TICKER = "ticker_gets_heads_up";
+
+    private static final String PERMISSION_SELF = "com.android.systemui.permission.SELF";
+
+    // Should match the values in PhoneWindowManager
+    public static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
+    public static final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
+
+    private static final String BANNER_ACTION_CANCEL =
+            "com.android.systemui.statusbar.banner_action_cancel";
+    private static final String BANNER_ACTION_SETUP =
+            "com.android.systemui.statusbar.banner_action_setup";
+    private static final String NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION
+            = "com.android.systemui.statusbar.work_challenge_unlocked_notification_action";
+    static final String TAG = "StatusBar";
+    public static final boolean DEBUG = false;
     public static final boolean SPEW = false;
     public static final boolean DUMPTRUCK = true; // extra dumpsys info
     public static final boolean DEBUG_GESTURES = false;
@@ -299,6 +382,14 @@
         FREEFORM_WINDOW_MANAGEMENT = freeformWindowManagement;
     }
 
+    /**
+     * The {@link StatusBarState} of the status bar.
+     */
+    protected int mState;
+    protected boolean mBouncerShowing;
+    protected boolean mShowLockscreenNotifications;
+    protected boolean mAllowLockscreenRemoteInput;
+
     PhoneStatusBarPolicy mIconPolicy;
 
     VolumeComponent mVolumeComponent;
@@ -309,7 +400,6 @@
 
     int mNaturalBarHeight = -1;
 
-    Display mDisplay;
     Point mCurrentDisplaySize = new Point();
 
     protected StatusBarWindowView mStatusBarWindow;
@@ -415,6 +505,7 @@
         }
     };
 
+    protected H mHandler = createHandler();
     final private ContentObserver mHeadsUpObserver = new ContentObserver(mHandler) {
         @Override
         public void onChange(boolean selfChange) {
@@ -522,6 +613,8 @@
     private Vibrator mVibrator;
     private long[] mCameraLaunchGestureVibePattern;
 
+    private final int[] mTmpInt2 = new int[2];
+
     // Fingerprint (as computed by getLoggingFingerprint() of the last logged state.
     private int mLastLoggedStateFingerprint;
 
@@ -613,7 +706,6 @@
     private NetworkController mNetworkController;
     private KeyguardMonitorImpl mKeyguardMonitor;
     private BatteryController mBatteryController;
-    private DeviceProvisionedController mDeviceProvisionedController;
 
     private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) {
         final int N = array.size();
@@ -625,6 +717,7 @@
 
     private final View.OnClickListener mGoToLockedShadeListener = v -> {
         if (mState == StatusBarState.KEYGUARD) {
+            wakeUpIfDozing(SystemClock.uptimeMillis(), v);
             goToLockedShade(null);
         }
     };
@@ -655,16 +748,156 @@
         mAssistManager = Dependency.get(AssistManager.class);
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
 
-        mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
-                .getDefaultDisplay();
+        mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
+        mDisplay = mWindowManager.getDefaultDisplay();
         updateDisplaySize();
         mScrimSrcModeEnabled = mContext.getResources().getBoolean(
                 R.bool.config_status_bar_scrim_behind_use_src);
 
         DateTimeView.setReceiverHandler(Dependency.get(Dependency.TIME_TICK_HANDLER));
-        putComponent(PhoneStatusBar.class, this);
+        putComponent(StatusBar.class, this);
 
-        super.start(); // calls createAndAddWindows()
+        // start old BaseStatusBar.start().
+        mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
+        mDevicePolicyManager = (DevicePolicyManager)mContext.getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+
+        mNotificationData = new NotificationData(this);
+
+        mAccessibilityManager = (AccessibilityManager)
+                mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
+
+        mDreamManager = IDreamManager.Stub.asInterface(
+                ServiceManager.checkService(DreamService.DREAM_SERVICE));
+        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+
+        mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
+        mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.ZEN_MODE), false,
+                mSettingsObserver);
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS), false,
+                mLockscreenSettingsObserver,
+                UserHandle.USER_ALL);
+        if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
+            mContext.getContentResolver().registerContentObserver(
+                    Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT),
+                    false,
+                    mSettingsObserver,
+                    UserHandle.USER_ALL);
+        }
+
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS),
+                true,
+                mLockscreenSettingsObserver,
+                UserHandle.USER_ALL);
+
+        mBarService = IStatusBarService.Stub.asInterface(
+                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+
+        mRecents = getComponent(Recents.class);
+
+        final Configuration currentConfig = mContext.getResources().getConfiguration();
+        mLocale = currentConfig.locale;
+        mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(mLocale);
+        mFontScale = currentConfig.fontScale;
+        mDensity = currentConfig.densityDpi;
+
+        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
+        mLockPatternUtils = new LockPatternUtils(mContext);
+
+        // Connect in to the status bar manager service
+        mCommandQueue = getComponent(CommandQueue.class);
+        mCommandQueue.addCallbacks(this);
+
+        int[] switches = new int[9];
+        ArrayList<IBinder> binders = new ArrayList<IBinder>();
+        ArrayList<String> iconSlots = new ArrayList<>();
+        ArrayList<StatusBarIcon> icons = new ArrayList<>();
+        Rect fullscreenStackBounds = new Rect();
+        Rect dockedStackBounds = new Rect();
+        try {
+            mBarService.registerStatusBar(mCommandQueue, iconSlots, icons, switches, binders,
+                    fullscreenStackBounds, dockedStackBounds);
+        } catch (RemoteException ex) {
+            // If the system process isn't there we're doomed anyway.
+        }
+
+        createAndAddWindows();
+
+        mSettingsObserver.onChange(false); // set up
+        disable(switches[0], switches[6], false /* animate */);
+        setSystemUiVisibility(switches[1], switches[7], switches[8], 0xffffffff,
+                fullscreenStackBounds, dockedStackBounds);
+        topAppWindowChanged(switches[2] != 0);
+        // StatusBarManagerService has a back up of IME token and it's restored here.
+        setImeWindowStatus(binders.get(0), switches[3], switches[4], switches[5] != 0);
+
+        // Set up the initial icon state
+        int N = iconSlots.size();
+        int viewIndex = 0;
+        for (int i=0; i < N; i++) {
+            setIcon(iconSlots.get(i), icons.get(i));
+        }
+
+        // Set up the initial notification state.
+        try {
+            mNotificationListener.registerAsSystemService(mContext,
+                    new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()),
+                    UserHandle.USER_ALL);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Unable to register notification listener", e);
+        }
+
+
+        if (DEBUG) {
+            Log.d(TAG, String.format(
+                    "init: icons=%d disabled=0x%08x lights=0x%08x menu=0x%08x imeButton=0x%08x",
+                   icons.size(),
+                   switches[0],
+                   switches[1],
+                   switches[2],
+                   switches[3]
+                   ));
+        }
+
+        mCurrentUserId = ActivityManager.getCurrentUser();
+        setHeadsUpUser(mCurrentUserId);
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_USER_SWITCHED);
+        filter.addAction(Intent.ACTION_USER_ADDED);
+        filter.addAction(Intent.ACTION_USER_PRESENT);
+        mContext.registerReceiver(mBaseBroadcastReceiver, filter);
+
+        IntentFilter internalFilter = new IntentFilter();
+        internalFilter.addAction(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION);
+        internalFilter.addAction(BANNER_ACTION_CANCEL);
+        internalFilter.addAction(BANNER_ACTION_SETUP);
+        mContext.registerReceiver(mBaseBroadcastReceiver, internalFilter, PERMISSION_SELF, null);
+
+        IntentFilter allUsersFilter = new IntentFilter();
+        allUsersFilter.addAction(
+                DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
+        allUsersFilter.addAction(Intent.ACTION_DEVICE_LOCKED_CHANGED);
+        mContext.registerReceiverAsUser(mAllUsersReceiver, UserHandle.ALL, allUsersFilter,
+                null, null);
+        updateCurrentProfilesCache();
+
+        IVrManager vrManager = IVrManager.Stub.asInterface(ServiceManager.getService("vrmanager"));
+        try {
+            vrManager.registerListener(mVrStateCallbacks);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to register VR mode state listener: " + e);
+        }
+
+        mNonBlockablePkgs = new HashSet<String>();
+        Collections.addAll(mNonBlockablePkgs, mContext.getResources().getStringArray(
+                com.android.internal.R.array.config_nonBlockableNotificationPackages));
+        // end old BaseStatusBar.start().
 
         mMediaSessionManager
                 = (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
@@ -777,7 +1010,7 @@
         mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
                 R.id.notification_stack_scroller);
         mStackScroller.setLongPressListener(getNotificationLongClicker());
-        mStackScroller.setPhoneStatusBar(this);
+        mStackScroller.setStatusBar(this);
         mStackScroller.setGroupManager(mGroupManager);
         mStackScroller.setHeadsUpManager(mHeadsUpManager);
         mGroupManager.setOnGroupChangeListener(mStackScroller);
@@ -861,7 +1094,7 @@
 
         initEmergencyCryptkeeperText();
 
-        mKeyguardBottomArea.setPhoneStatusBar(this);
+        mKeyguardBottomArea.setStatusBar(this);
         mKeyguardBottomArea.setUserSetupComplete(mUserSetup);
         if (UserManager.get(mContext).isUserSwitcherEnabled()) {
             createUserSwitcher();
@@ -1000,9 +1233,21 @@
         mNotificationShelf.setStatusBarState(mState);
     }
 
-    @Override
     protected void onDensityOrFontScaleChanged() {
-        super.onDensityOrFontScaleChanged();
+        // start old BaseStatusBar.onDensityOrFontScaleChanged().
+        ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
+        for (int i = 0; i < activeNotifications.size(); i++) {
+            Entry entry = activeNotifications.get(i);
+            boolean exposedGuts = mNotificationGutsExposed != null
+                    && entry.row.getGuts() == mNotificationGutsExposed;
+            entry.row.reInflateViews();
+            if (exposedGuts) {
+                mNotificationGutsExposed = entry.row.getGuts();
+                bindGuts(entry.row, mGutsMenuItem);
+            }
+            inflateViews(entry, mStackScroller);
+        }
+        // end old BaseStatusBar.onDensityOrFontScaleChanged().
         mScrimController.onDensityOrFontScaleChanged();
         mStatusBarView.onDensityOrFontScaleChanged();
         if (mBrightnessMirrorController != null) {
@@ -1015,7 +1260,7 @@
         inflateEmptyShadeView();
         updateEmptyShadeView();
         mStatusBarKeyguardViewManager.onDensityOrFontScaleChanged();
-        // TODO: Bring these out of PhoneStatusBar.
+        // TODO: Bring these out of StatusBar.
         ((UserInfoControllerImpl) Dependency.get(UserInfoController.class))
                 .onDensityOrFontScaleChanged();
         Dependency.get(UserSwitcherController.class).onDensityOrFontScaleChanged();
@@ -1161,16 +1406,20 @@
         }
     }
 
-    @Override
     protected void setZenMode(int mode) {
-        super.setZenMode(mode);
+        // start old BaseStatusBar.setZenMode().
+        if (isDeviceProvisioned()) {
+            mZenMode = mode;
+            updateNotifications();
+        }
+        // end old BaseStatusBar.setZenMode().
         if (mIconPolicy != null) {
             mIconPolicy.setZenMode(mode);
         }
     }
 
     protected void startKeyguard() {
-        Trace.beginSection("PhoneStatusBar#startKeyguard");
+        Trace.beginSection("StatusBar#startKeyguard");
         KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);
         mFingerprintUnlockController = new FingerprintUnlockController(mContext,
                 mStatusBarWindowManager, mDozeScrimController, keyguardViewMediator,
@@ -1210,7 +1459,6 @@
         Trace.endSection();
     }
 
-    @Override
     protected View getStatusBarView() {
         return mStatusBarView;
     }
@@ -1232,7 +1480,6 @@
         return mNaturalBarHeight;
     }
 
-    @Override
     protected boolean toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction) {
         if (mRecents == null) {
             return false;
@@ -1280,7 +1527,6 @@
         return new UserHandle(mCurrentUserId);
     }
 
-    @Override
     public void addNotification(StatusBarNotification notification, RankingMap ranking,
             Entry oldEntry) {
         if (DEBUG) Log.d(TAG, "addNotification key=" + notification.getKey());
@@ -1343,13 +1589,11 @@
         }
     }
 
-    @Override
     protected void updateNotificationRanking(RankingMap ranking) {
         mNotificationData.updateRanking(ranking);
         updateNotifications();
     }
 
-    @Override
     public void removeNotification(String key, RankingMap ranking) {
         boolean deferRemoval = false;
         if (mHeadsUpManager.isHeadsUp(key)) {
@@ -1480,13 +1724,28 @@
         }
     }
 
-    @Override
     protected void performRemoveNotification(StatusBarNotification n) {
         Entry entry = mNotificationData.get(n.getKey());
         if (mRemoteInputController.isRemoteInputActive(entry)) {
             mRemoteInputController.removeRemoteInput(entry, null);
         }
-        super.performRemoveNotification(n);
+        // start old BaseStatusBar.performRemoveNotification.
+        final String pkg = n.getPackageName();
+        final String tag = n.getTag();
+        final int id = n.getId();
+        final int userId = n.getUserId();
+        try {
+            mBarService.onNotificationClear(pkg, tag, id, userId);
+            if (FORCE_REMOTE_INPUT_HISTORY
+                    && mKeysKeptForRemoteInput.contains(n.getKey())) {
+                mKeysKeptForRemoteInput.remove(n.getKey());
+            }
+            removeNotification(n.getKey(), null);
+
+        } catch (RemoteException ex) {
+            // system process is dead if we're here.
+        }
+        // end old BaseStatusBar.performRemoveNotification.
     }
 
     private void updateNotificationShade() {
@@ -1715,17 +1974,14 @@
         }
     }
 
-    @Override
     public void addQsTile(ComponentName tile) {
         mQSPanel.getHost().addTile(tile);
     }
 
-    @Override
     public void remQsTile(ComponentName tile) {
         mQSPanel.getHost().removeTile(tile);
     }
 
-    @Override
     public void clickTile(ComponentName tile) {
         mQSPanel.clickTile(tile);
     }
@@ -1788,7 +2044,6 @@
         return entry.row.getParent() instanceof NotificationStackScrollLayout;
     }
 
-    @Override
     protected void updateNotifications() {
         mNotificationData.filterAndSort();
 
@@ -1799,7 +2054,6 @@
         updateNotifications();
     }
 
-    @Override
     protected void setAreThereNotifications() {
 
         if (SPEW) {
@@ -1983,7 +2237,7 @@
      * Refresh or remove lockscreen artwork from media metadata or the lockscreen wallpaper.
      */
     public void updateMediaMetaData(boolean metaDataChanged, boolean allowEnterAnimation) {
-        Trace.beginSection("PhoneStatusBar#updateMediaMetaData");
+        Trace.beginSection("StatusBar#updateMediaMetaData");
         if (!SHOW_LOCKSCREEN_MEDIA_ARTWORK) {
             Trace.endSection();
             return;
@@ -2278,9 +2532,8 @@
         disable(mDisabledUnmodified1, mDisabledUnmodified2, animate);
     }
 
-    @Override
-    protected BaseStatusBar.H createHandler() {
-        return new PhoneStatusBar.H();
+    protected H createHandler() {
+        return new StatusBar.H();
     }
 
     @Override
@@ -2317,7 +2570,6 @@
         return getBarState() == StatusBarState.KEYGUARD;
     }
 
-    @Override
     public boolean isDozing() {
         return mDozing;
     }
@@ -2411,7 +2663,6 @@
 
     }
 
-    @Override
     protected void updateHeadsUp(String key, Entry entry, boolean shouldPeek,
             boolean alertAgain) {
         final boolean wasHeadsUp = isHeadsUp(key);
@@ -2428,7 +2679,6 @@
         }
     }
 
-    @Override
     protected void setHeadsUpUser(int newUserId) {
         if (mHeadsUpManager != null) {
             mHeadsUpManager.setUser(newUserId);
@@ -2439,7 +2689,6 @@
         return mHeadsUpManager.isHeadsUp(key);
     }
 
-    @Override
     protected boolean isSnoozedPackage(StatusBarNotification sbn) {
         return mHeadsUpManager.isSnoozed(sbn.getPackageName());
     }
@@ -2496,11 +2745,39 @@
     /**
      * All changes to the status bar and notifications funnel through here and are batched.
      */
-    private class H extends BaseStatusBar.H {
+    protected class H extends Handler {
         @Override
         public void handleMessage(Message m) {
-            super.handleMessage(m);
             switch (m.what) {
+                // start old BaseStatusBar.H handling.
+                case MSG_SHOW_RECENT_APPS:
+                    showRecents(m.arg1 > 0, m.arg2 != 0);
+                    break;
+                case MSG_HIDE_RECENT_APPS:
+                    hideRecents(m.arg1 > 0, m.arg2 > 0);
+                    break;
+                case MSG_TOGGLE_RECENTS_APPS:
+                    toggleRecents();
+                    break;
+                case MSG_PRELOAD_RECENT_APPS:
+                    preloadRecents();
+                    break;
+                case MSG_CANCEL_PRELOAD_RECENT_APPS:
+                    cancelPreloadingRecents();
+                    break;
+                case MSG_SHOW_NEXT_AFFILIATED_TASK:
+                    showRecentsNextAffiliatedTask();
+                    break;
+                case MSG_SHOW_PREV_AFFILIATED_TASK:
+                    showRecentsPreviousAffiliatedTask();
+                    break;
+                case MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU:
+                    toggleKeyboardShortcuts(m.arg1);
+                    break;
+                case MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU:
+                    dismissKeyboardShortcuts();
+                    break;
+                // End old BaseStatusBar.H handling.
                 case MSG_OPEN_NOTIFICATION_PANEL:
                     animateExpandNotificationsPanel();
                     break;
@@ -2517,7 +2794,6 @@
         }
     }
 
-    @Override
     public void maybeEscalateHeadsUp() {
         Collection<HeadsUpManager.HeadsUpEntry> entries = mHeadsUpManager.getAllEntries();
         for (HeadsUpManager.HeadsUpEntry entry : entries) {
@@ -2617,12 +2893,10 @@
                 1.0f /* speedUpFactor */);
     }
 
-    @Override
     public void animateCollapsePanels(int flags, boolean force) {
         animateCollapsePanels(flags, force, false /* delayed */, 1.0f /* speedUpFactor */);
     }
 
-    @Override
     public void animateCollapsePanels(int flags, boolean force, boolean delayed) {
         animateCollapsePanels(flags, force, delayed, 1.0f /* speedUpFactor */);
     }
@@ -2947,7 +3221,6 @@
         }
     };
 
-    @Override
     public void setInteracting(int barWindow, boolean interacting) {
         final boolean changing = ((mInteractingWindows & barWindow) != 0) != interacting;
         mInteractingWindows = interacting
@@ -3169,7 +3442,6 @@
         pw.println(BarTransitions.modeToString(transitions.getMode()));
     }
 
-    @Override
     public void createAndAddWindows() {
         addStatusBarWindow();
     }
@@ -3352,7 +3624,6 @@
         }
     }
 
-    @Override
     protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) {
         dismissKeyguardThenExecute(action, null /* cancelRunnable */, afterKeyguardGone);
     }
@@ -3372,7 +3643,15 @@
     protected void onConfigurationChanged(Configuration newConfig) {
         updateResources();
         updateDisplaySize(); // populates mDisplayMetrics
-        super.onConfigurationChanged(newConfig); // calls refreshLayout
+        // Begin old BaseStatusBar.onConfigurationChanged
+        final float fontScale = newConfig.fontScale;
+        final int density = newConfig.densityDpi;
+        if (density != mDensity || mFontScale != fontScale) {
+            onDensityOrFontScaleChanged();
+            mDensity = density;
+            mFontScale = fontScale;
+        }
+        // End old BaseStatusBar.onConfigurationChanged
 
         if (DEBUG) {
             Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration());
@@ -3382,9 +3661,10 @@
         mScreenPinningRequest.onConfigurationChanged();
     }
 
-    @Override
     public void userSwitched(int newUserId) {
-        super.userSwitched(newUserId);
+        // Begin old BaseStatusBar.userSwitched
+        setHeadsUpUser(newUserId);
+        // End old BaseStatusBar.userSwitched
         if (MULTIUSER_DEBUG) mNotificationPanelDebugText.setText("USER " + newUserId);
         animateCollapsePanels();
         updatePublicMode();
@@ -3439,14 +3719,40 @@
 
     // Visibility reporting
 
-    @Override
     protected void handleVisibleToUserChanged(boolean visibleToUser) {
         if (visibleToUser) {
-            super.handleVisibleToUserChanged(visibleToUser);
+            handleVisibleToUserChangedImpl(visibleToUser);
             startNotificationLogging();
         } else {
             stopNotificationLogging();
-            super.handleVisibleToUserChanged(visibleToUser);
+            handleVisibleToUserChangedImpl(visibleToUser);
+        }
+    }
+
+    /**
+     * The LEDs are turned off when the notification panel is shown, even just a little bit.
+     * See also StatusBar.setPanelExpanded for another place where we attempt to do this.
+     */
+    // Old BaseStatusBar.handleVisibileToUserChanged
+    private void handleVisibleToUserChangedImpl(boolean visibleToUser) {
+        try {
+            if (visibleToUser) {
+                boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp();
+                boolean clearNotificationEffects =
+                        !isPanelFullyCollapsed() &&
+                        (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED);
+                int notificationLoad = mNotificationData.getActiveNotifications().size();
+                if (pinnedHeadsUp && isPanelFullyCollapsed())  {
+                    notificationLoad = 1;
+                } else {
+                    MetricsLogger.histogram(mContext, "note_load", notificationLoad);
+                }
+                mBarService.onPanelRevealed(clearNotificationEffects, notificationLoad);
+            } else {
+                mBarService.onPanelHidden();
+            }
+        } catch (RemoteException ex) {
+            // Won't fail unless the world has ended.
         }
     }
 
@@ -3637,9 +3943,16 @@
         }
     }
 
-    @Override
     public void destroy() {
-        super.destroy();
+        // Begin old BaseStatusBar.destroy().
+        mContext.unregisterReceiver(mBaseBroadcastReceiver);
+        try {
+            mNotificationListener.unregisterAsSystemService();
+        } catch (RemoteException e) {
+            // Ignore.
+        }
+        mDeviceProvisionedController.removeCallback(mDeviceProvisionedListener);
+        // End old BaseStatusBar.destroy().
         if (mStatusBarWindow != null) {
             mWindowManager.removeViewImmediate(mStatusBarWindow);
             mStatusBarWindow = null;
@@ -3744,7 +4057,6 @@
         return mState;
     }
 
-    @Override
     public boolean isPanelFullyCollapsed() {
         return mNotificationPanel.isFullyCollapsed();
     }
@@ -3793,12 +4105,10 @@
         updateMediaMetaData(true /* metaDataChanged */, true);
     }
 
-    @Override
     public boolean isCollapsing() {
         return mNotificationPanel.isCollapsing();
     }
 
-    @Override
     public void addPostCollapseAction(Runnable r) {
         mPostCollapseRunnables.add(r);
     }
@@ -3912,7 +4222,7 @@
      * @return true if we would like to stay in the shade, false if it should go away entirely
      */
     public boolean hideKeyguard() {
-        Trace.beginSection("PhoneStatusBar#hideKeyguard");
+        Trace.beginSection("StatusBar#hideKeyguard");
         boolean staying = mLeaveOpenOnKeyguardHide;
         setBarState(StatusBarState.SHADE);
         View viewToClick = null;
@@ -4044,7 +4354,7 @@
     }
 
     protected void updateKeyguardState(boolean goingToFullShade, boolean fromShadeLocked) {
-        Trace.beginSection("PhoneStatusBar#updateKeyguardState");
+        Trace.beginSection("StatusBar#updateKeyguardState");
         if (mState == StatusBarState.KEYGUARD) {
             mKeyguardIndicationController.setVisible(true);
             mNotificationPanel.resetViews();
@@ -4081,7 +4391,7 @@
     }
 
     private void updateDozingState() {
-        Trace.beginSection("PhoneStatusBar#updateDozingState");
+        Trace.beginSection("StatusBar#updateDozingState");
         boolean animate = !mDozing && mDozeScrimController.isPulsing();
         mNotificationPanel.setDozing(mDozing, animate);
         mStackScroller.setDark(mDozing, animate, mWakeUpTouchLocation);
@@ -4287,7 +4597,6 @@
         }
     }
 
-    @Override
     protected int getMaxKeyguardNotifications(boolean recompute) {
         if (recompute) {
             mMaxKeyguardNotifications = Math.max(1,
@@ -4387,29 +4696,63 @@
         }
     }
 
-    @Override
     public void onLockedNotificationImportanceChange(OnDismissAction dismissAction) {
         mLeaveOpenOnKeyguardHide = true;
         dismissKeyguardThenExecute(dismissAction, true /* afterKeyguardGone */);
     }
 
-    @Override
     protected void onLockedRemoteInput(ExpandableNotificationRow row, View clicked) {
         mLeaveOpenOnKeyguardHide = true;
         showBouncer();
         mPendingRemoteInputView = clicked;
     }
 
-    @Override
+    protected void onMakeExpandedVisibleForRemoteInput(ExpandableNotificationRow row,
+            View clickedView) {
+        if (isKeyguardShowing()) {
+            onLockedRemoteInput(row, clickedView);
+        } else {
+            row.setUserExpanded(true);
+            row.getPrivateLayout().setOnExpandedVisibleListener(clickedView::performClick);
+        }
+    }
+
     protected boolean startWorkChallengeIfNecessary(int userId, IntentSender intendSender,
             String notificationKey) {
         // Clear pending remote view, as we do not want to trigger pending remote input view when
         // it's called by other code
         mPendingWorkRemoteInputView = null;
-        return super.startWorkChallengeIfNecessary(userId, intendSender, notificationKey);
+        // Begin old BaseStatusBar.startWorkChallengeIfNecessary.
+        final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null,
+                null, userId);
+        if (newIntent == null) {
+            return false;
+        }
+        final Intent callBackIntent = new Intent(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION);
+        callBackIntent.putExtra(Intent.EXTRA_INTENT, intendSender);
+        callBackIntent.putExtra(Intent.EXTRA_INDEX, notificationKey);
+        callBackIntent.setPackage(mContext.getPackageName());
+
+        PendingIntent callBackPendingIntent = PendingIntent.getBroadcast(
+                mContext,
+                0,
+                callBackIntent,
+                PendingIntent.FLAG_CANCEL_CURRENT |
+                        PendingIntent.FLAG_ONE_SHOT |
+                        PendingIntent.FLAG_IMMUTABLE);
+        newIntent.putExtra(
+                Intent.EXTRA_INTENT,
+                callBackPendingIntent.getIntentSender());
+        try {
+            ActivityManager.getService().startConfirmDeviceCredentialIntent(newIntent,
+                    null /*options*/);
+        } catch (RemoteException ex) {
+            // ignore
+        }
+        return true;
+        // End old BaseStatusBar.startWorkChallengeIfNecessary.
     }
 
-    @Override
     protected void onLockedWorkRemoteInput(int userId, ExpandableNotificationRow row,
             View clicked) {
         // Collapse notification and show work challenge
@@ -4429,7 +4772,6 @@
         return false;
     }
 
-    @Override
     protected void onWorkChallengeChanged() {
         updatePublicMode();
         updateNotifications();
@@ -4526,9 +4868,8 @@
         return mKeyguardFadingAwayDuration;
     }
 
-    @Override
     public void setBouncerShowing(boolean bouncerShowing) {
-        super.setBouncerShowing(bouncerShowing);
+        mBouncerShowing = bouncerShowing;
         mStatusBarView.setBouncerShowing(bouncerShowing);
         recomputeDisableFlags(true /* animate */);
     }
@@ -4608,13 +4949,14 @@
         return !mNotificationData.getActiveNotifications().isEmpty();
     }
 
-    @Override
-    public void wakeUpIfDozing(long time, PointF where) {
+    public void wakeUpIfDozing(long time, View where) {
         if (mDozing && mDozeScrimController.isPulsing()) {
             PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
             pm.wakeUp(time, "com.android.systemui:NODOZE");
             mWakeUpComingFromTouch = true;
-            mWakeUpTouchLocation = where;
+            where.getLocationInWindow(mTmpInt2);
+            mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2,
+                    mTmpInt2[1] + where.getHeight() / 2);
             mNotificationPanel.setTouchDisabled(false);
             mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
             mFalsingManager.onScreenOnFromTouch();
@@ -4702,7 +5044,7 @@
     }
 
     private void updateDozing() {
-        Trace.beginSection("PhoneStatusBar#updateDozing");
+        Trace.beginSection("StatusBar#updateDozing");
         // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked.
         mDozing = mDozingRequested && mState == StatusBarState.KEYGUARD
                 || mFingerprintUnlockController.getMode()
@@ -4854,8 +5196,2033 @@
 
         @Override
         public void startPendingIntentDismissingKeyguard(PendingIntent intent) {
-            PhoneStatusBar.this.startPendingIntentDismissingKeyguard(intent);
+            StatusBar.this.startPendingIntentDismissingKeyguard(intent);
         }
 
     }
+
+    public SnoozeListener getSnoozeListener() {
+        return this;
+    }
+
+    @Override
+    public void snoozeNotification(StatusBarNotification sbn, SnoozeOption snoozeOption) {
+        setNotificationSnoozed(sbn, snoozeOption);
+    }
+
+    // Begin Extra BaseStatusBar methods.
+
+    protected CommandQueue mCommandQueue;
+    protected IStatusBarService mBarService;
+
+    // all notifications
+    protected NotificationData mNotificationData;
+    protected NotificationStackScrollLayout mStackScroller;
+
+    protected NotificationGroupManager mGroupManager = new NotificationGroupManager();
+
+    protected RemoteInputController mRemoteInputController;
+
+    // for heads up notifications
+    protected HeadsUpManager mHeadsUpManager;
+
+    // handling reordering
+    protected VisualStabilityManager mVisualStabilityManager = new VisualStabilityManager();
+
+    protected int mCurrentUserId = 0;
+    final protected SparseArray<UserInfo> mCurrentProfiles = new SparseArray<UserInfo>();
+
+    protected int mLayoutDirection = -1; // invalid
+    protected AccessibilityManager mAccessibilityManager;
+
+    protected boolean mDeviceInteractive;
+
+    protected boolean mVisible;
+    protected ArraySet<Entry> mHeadsUpEntriesToRemoveOnSwitch = new ArraySet<>();
+    protected ArraySet<Entry> mRemoteInputEntriesToRemoveOnCollapse = new ArraySet<>();
+
+    /**
+     * Notifications with keys in this set are not actually around anymore. We kept them around
+     * when they were canceled in response to a remote input interaction. This allows us to show
+     * what you replied and allows you to continue typing into it.
+     */
+    protected ArraySet<String> mKeysKeptForRemoteInput = new ArraySet<>();
+
+    // mScreenOnFromKeyguard && mVisible.
+    private boolean mVisibleToUser;
+
+    private Locale mLocale;
+    private float mFontScale;
+
+    protected boolean mUseHeadsUp = false;
+    protected boolean mHeadsUpTicker = false;
+    protected boolean mDisableNotificationAlerts = false;
+
+    protected DevicePolicyManager mDevicePolicyManager;
+    protected IDreamManager mDreamManager;
+    protected PowerManager mPowerManager;
+    protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+
+    // public mode, private notifications, etc
+    private final SparseBooleanArray mLockscreenPublicMode = new SparseBooleanArray();
+    private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
+    private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray();
+
+    private UserManager mUserManager;
+    private int mDensity;
+
+    protected KeyguardManager mKeyguardManager;
+    private LockPatternUtils mLockPatternUtils;
+    private DeviceProvisionedController mDeviceProvisionedController;
+
+    // UI-specific methods
+
+    protected WindowManager mWindowManager;
+    protected IWindowManager mWindowManagerService;
+
+    protected Display mDisplay;
+
+    protected RecentsComponent mRecents;
+
+    protected int mZenMode;
+
+    // which notification is currently being longpress-examined by the user
+    private NotificationGuts mNotificationGutsExposed;
+    private MenuItem mGutsMenuItem;
+
+    private KeyboardShortcuts mKeyboardShortcuts;
+
+    protected NotificationShelf mNotificationShelf;
+    protected DismissView mDismissView;
+    protected EmptyShadeView mEmptyShadeView;
+
+    private NotificationClicker mNotificationClicker = new NotificationClicker();
+
+    protected AssistManager mAssistManager;
+
+    protected boolean mVrMode;
+
+    private Set<String> mNonBlockablePkgs;
+
+    @Override  // NotificationData.Environment
+    public boolean isDeviceProvisioned() {
+        return mDeviceProvisionedController.isDeviceProvisioned();
+    }
+
+    private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
+        @Override
+        public void onVrStateChanged(boolean enabled) {
+            mVrMode = enabled;
+        }
+    };
+
+    public boolean isDeviceInVrMode() {
+        return mVrMode;
+    }
+
+    private final DeviceProvisionedListener mDeviceProvisionedListener =
+            new DeviceProvisionedListener() {
+        @Override
+        public void onDeviceProvisionedChanged() {
+            updateNotifications();
+        }
+    };
+
+    protected final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
+        @Override
+        public void onChange(boolean selfChange) {
+            final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
+            setZenMode(mode);
+
+            updateLockscreenNotificationSetting();
+        }
+    };
+
+    private final ContentObserver mLockscreenSettingsObserver = new ContentObserver(mHandler) {
+        @Override
+        public void onChange(boolean selfChange) {
+            // We don't know which user changed LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS or
+            // LOCK_SCREEN_SHOW_NOTIFICATIONS, so we just dump our cache ...
+            mUsersAllowingPrivateNotifications.clear();
+            mUsersAllowingNotifications.clear();
+            // ... and refresh all the notifications
+            updateLockscreenNotificationSetting();
+            updateNotifications();
+        }
+    };
+
+    private RemoteViews.OnClickHandler mOnClickHandler = new RemoteViews.OnClickHandler() {
+
+        @Override
+        public boolean onClickHandler(
+                final View view, final PendingIntent pendingIntent, final Intent fillInIntent) {
+            wakeUpIfDozing(SystemClock.uptimeMillis(), view);
+
+
+            if (handleRemoteInput(view, pendingIntent, fillInIntent)) {
+                return true;
+            }
+
+            if (DEBUG) {
+                Log.v(TAG, "Notification click handler invoked for intent: " + pendingIntent);
+            }
+            logActionClick(view);
+            // The intent we are sending is for the application, which
+            // won't have permission to immediately start an activity after
+            // the user switches to home.  We know it is safe to do at this
+            // point, so make sure new activity switches are now allowed.
+            try {
+                ActivityManager.getService().resumeAppSwitches();
+            } catch (RemoteException e) {
+            }
+            final boolean isActivity = pendingIntent.isActivity();
+            if (isActivity) {
+                final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
+                final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
+                        mContext, pendingIntent.getIntent(), mCurrentUserId);
+                dismissKeyguardThenExecute(new OnDismissAction() {
+                    @Override
+                    public boolean onDismiss() {
+                        try {
+                            ActivityManager.getService().resumeAppSwitches();
+                        } catch (RemoteException e) {
+                        }
+
+                        boolean handled = superOnClickHandler(view, pendingIntent, fillInIntent);
+
+                        // close the shade if it was open
+                        if (handled) {
+                            animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
+                                    true /* force */);
+                            visibilityChanged(false);
+                            mAssistManager.hideAssist();
+                        }
+
+                        // Wait for activity start.
+                        return handled;
+                    }
+                }, afterKeyguardGone);
+                return true;
+            } else {
+                return superOnClickHandler(view, pendingIntent, fillInIntent);
+            }
+        }
+
+        private void logActionClick(View view) {
+            ViewParent parent = view.getParent();
+            String key = getNotificationKeyForParent(parent);
+            if (key == null) {
+                Log.w(TAG, "Couldn't determine notification for click.");
+                return;
+            }
+            int index = -1;
+            // If this is a default template, determine the index of the button.
+            if (view.getId() == com.android.internal.R.id.action0 &&
+                    parent != null && parent instanceof ViewGroup) {
+                ViewGroup actionGroup = (ViewGroup) parent;
+                index = actionGroup.indexOfChild(view);
+            }
+            try {
+                mBarService.onNotificationActionClick(key, index);
+            } catch (RemoteException e) {
+                // Ignore
+            }
+        }
+
+        private String getNotificationKeyForParent(ViewParent parent) {
+            while (parent != null) {
+                if (parent instanceof ExpandableNotificationRow) {
+                    return ((ExpandableNotificationRow) parent).getStatusBarNotification().getKey();
+                }
+                parent = parent.getParent();
+            }
+            return null;
+        }
+
+        private boolean superOnClickHandler(View view, PendingIntent pendingIntent,
+                Intent fillInIntent) {
+            return super.onClickHandler(view, pendingIntent, fillInIntent,
+                    StackId.FULLSCREEN_WORKSPACE_STACK_ID);
+        }
+
+        private boolean handleRemoteInput(View view, PendingIntent pendingIntent, Intent fillInIntent) {
+            Object tag = view.getTag(com.android.internal.R.id.remote_input_tag);
+            RemoteInput[] inputs = null;
+            if (tag instanceof RemoteInput[]) {
+                inputs = (RemoteInput[]) tag;
+            }
+
+            if (inputs == null) {
+                return false;
+            }
+
+            RemoteInput input = null;
+
+            for (RemoteInput i : inputs) {
+                if (i.getAllowFreeFormInput()) {
+                    input = i;
+                }
+            }
+
+            if (input == null) {
+                return false;
+            }
+
+            ViewParent p = view.getParent();
+            RemoteInputView riv = null;
+            while (p != null) {
+                if (p instanceof View) {
+                    View pv = (View) p;
+                    if (pv.isRootNamespace()) {
+                        riv = findRemoteInputView(pv);
+                        break;
+                    }
+                }
+                p = p.getParent();
+            }
+            ExpandableNotificationRow row = null;
+            while (p != null) {
+                if (p instanceof ExpandableNotificationRow) {
+                    row = (ExpandableNotificationRow) p;
+                    break;
+                }
+                p = p.getParent();
+            }
+
+            if (row == null) {
+                return false;
+            }
+
+            row.setUserExpanded(true);
+
+            if (!mAllowLockscreenRemoteInput) {
+                final int userId = pendingIntent.getCreatorUserHandle().getIdentifier();
+                if (isLockscreenPublicMode(userId)) {
+                    onLockedRemoteInput(row, view);
+                    return true;
+                }
+                if (mUserManager.getUserInfo(userId).isManagedProfile()
+                        && mKeyguardManager.isDeviceLocked(userId)) {
+                    onLockedWorkRemoteInput(userId, row, view);
+                    return true;
+                }
+            }
+
+            if (riv == null) {
+                riv = findRemoteInputView(row.getPrivateLayout().getExpandedChild());
+                if (riv == null) {
+                    return false;
+                }
+                if (!row.getPrivateLayout().getExpandedChild().isShown()) {
+                    onMakeExpandedVisibleForRemoteInput(row, view);
+                    return true;
+                }
+            }
+
+            int width = view.getWidth();
+            if (view instanceof TextView) {
+                // Center the reveal on the text which might be off-center from the TextView
+                TextView tv = (TextView) view;
+                if (tv.getLayout() != null) {
+                    int innerWidth = (int) tv.getLayout().getLineWidth(0);
+                    innerWidth += tv.getCompoundPaddingLeft() + tv.getCompoundPaddingRight();
+                    width = Math.min(width, innerWidth);
+                }
+            }
+            int cx = view.getLeft() + width / 2;
+            int cy = view.getTop() + view.getHeight() / 2;
+            int w = riv.getWidth();
+            int h = riv.getHeight();
+            int r = Math.max(
+                    Math.max(cx + cy, cx + (h - cy)),
+                    Math.max((w - cx) + cy, (w - cx) + (h - cy)));
+
+            riv.setRevealParameters(cx, cy, r);
+            riv.setPendingIntent(pendingIntent);
+            riv.setRemoteInput(inputs, input);
+            riv.focusAnimated();
+
+            return true;
+        }
+
+        private RemoteInputView findRemoteInputView(View v) {
+            if (v == null) {
+                return null;
+            }
+            return (RemoteInputView) v.findViewWithTag(RemoteInputView.VIEW_TAG);
+        }
+    };
+
+    private final BroadcastReceiver mBaseBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+                mCurrentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+                updateCurrentProfilesCache();
+                if (true) Log.v(TAG, "userId " + mCurrentUserId + " is in the house");
+
+                updateLockscreenNotificationSetting();
+
+                userSwitched(mCurrentUserId);
+            } else if (Intent.ACTION_USER_ADDED.equals(action)) {
+                updateCurrentProfilesCache();
+            } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
+                List<ActivityManager.RecentTaskInfo> recentTask = null;
+                try {
+                    recentTask = ActivityManager.getService().getRecentTasks(1,
+                            ActivityManager.RECENT_WITH_EXCLUDED
+                            | ActivityManager.RECENT_INCLUDE_PROFILES,
+                            mCurrentUserId).getList();
+                } catch (RemoteException e) {
+                    // Abandon hope activity manager not running.
+                }
+                if (recentTask != null && recentTask.size() > 0) {
+                    UserInfo user = mUserManager.getUserInfo(recentTask.get(0).userId);
+                    if (user != null && user.isManagedProfile()) {
+                        Toast toast = Toast.makeText(mContext,
+                                R.string.managed_profile_foreground_toast,
+                                Toast.LENGTH_SHORT);
+                        TextView text = (TextView) toast.getView().findViewById(
+                                android.R.id.message);
+                        text.setCompoundDrawablesRelativeWithIntrinsicBounds(
+                                R.drawable.stat_sys_managed_profile_status, 0, 0, 0);
+                        int paddingPx = mContext.getResources().getDimensionPixelSize(
+                                R.dimen.managed_profile_toast_padding);
+                        text.setCompoundDrawablePadding(paddingPx);
+                        toast.show();
+                    }
+                }
+            } else if (BANNER_ACTION_CANCEL.equals(action) || BANNER_ACTION_SETUP.equals(action)) {
+                NotificationManager noMan = (NotificationManager)
+                        mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+                noMan.cancel(SystemMessage.NOTE_HIDDEN_NOTIFICATIONS);
+
+                Settings.Secure.putInt(mContext.getContentResolver(),
+                        Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0);
+                if (BANNER_ACTION_SETUP.equals(action)) {
+                    animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
+                            true /* force */);
+                    mContext.startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_REDACTION)
+                            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+
+                    );
+                }
+            } else if (NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION.equals(action)) {
+                final IntentSender intentSender = intent.getParcelableExtra(Intent.EXTRA_INTENT);
+                final String notificationKey = intent.getStringExtra(Intent.EXTRA_INDEX);
+                if (intentSender != null) {
+                    try {
+                        mContext.startIntentSender(intentSender, null, 0, 0, 0);
+                    } catch (IntentSender.SendIntentException e) {
+                        /* ignore */
+                    }
+                }
+                if (notificationKey != null) {
+                    try {
+                        mBarService.onNotificationClick(notificationKey);
+                    } catch (RemoteException e) {
+                        /* ignore */
+                    }
+                }
+            }
+        }
+    };
+
+    private final BroadcastReceiver mAllUsersReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+
+            if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action) &&
+                    isCurrentProfile(getSendingUserId())) {
+                mUsersAllowingPrivateNotifications.clear();
+                updateLockscreenNotificationSetting();
+                updateNotifications();
+            } else if (Intent.ACTION_DEVICE_LOCKED_CHANGED.equals(action)) {
+                if (userId != mCurrentUserId && isCurrentProfile(userId)) {
+                    onWorkChallengeChanged();
+                }
+            }
+        }
+    };
+
+    private final NotificationListenerService mNotificationListener =
+            new NotificationListenerService() {
+        @Override
+        public void onListenerConnected() {
+            if (DEBUG) Log.d(TAG, "onListenerConnected");
+            final StatusBarNotification[] notifications = getActiveNotifications();
+            if (notifications == null) {
+                Log.w(TAG, "onListenerConnected unable to get active notifications.");
+                return;
+            }
+            final RankingMap currentRanking = getCurrentRanking();
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    for (StatusBarNotification sbn : notifications) {
+                        addNotification(sbn, currentRanking, null /* oldEntry */);
+                    }
+                }
+            });
+        }
+
+        @Override
+        public void onNotificationPosted(final StatusBarNotification sbn,
+                final RankingMap rankingMap) {
+            if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn);
+            if (sbn != null) {
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        processForRemoteInput(sbn.getNotification());
+                        String key = sbn.getKey();
+                        mKeysKeptForRemoteInput.remove(key);
+                        boolean isUpdate = mNotificationData.get(key) != null;
+                        // In case we don't allow child notifications, we ignore children of
+                        // notifications that have a summary, since we're not going to show them
+                        // anyway. This is true also when the summary is canceled,
+                        // because children are automatically canceled by NoMan in that case.
+                        if (!ENABLE_CHILD_NOTIFICATIONS
+                            && mGroupManager.isChildInGroupWithSummary(sbn)) {
+                            if (DEBUG) {
+                                Log.d(TAG, "Ignoring group child due to existing summary: " + sbn);
+                            }
+
+                            // Remove existing notification to avoid stale data.
+                            if (isUpdate) {
+                                removeNotification(key, rankingMap);
+                            } else {
+                                mNotificationData.updateRanking(rankingMap);
+                            }
+                            return;
+                        }
+                        if (isUpdate) {
+                            updateNotification(sbn, rankingMap);
+                        } else {
+                            addNotification(sbn, rankingMap, null /* oldEntry */);
+                        }
+                    }
+                });
+            }
+        }
+
+        @Override
+        public void onNotificationRemoved(StatusBarNotification sbn,
+                final RankingMap rankingMap) {
+            if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn);
+            if (sbn != null) {
+                final String key = sbn.getKey();
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        removeNotification(key, rankingMap);
+                    }
+                });
+            }
+        }
+
+        @Override
+        public void onNotificationRankingUpdate(final RankingMap rankingMap) {
+            if (DEBUG) Log.d(TAG, "onRankingUpdate");
+            if (rankingMap != null) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    updateNotificationRanking(rankingMap);
+                }
+            });
+        }                            }
+
+    };
+
+    private void updateCurrentProfilesCache() {
+        synchronized (mCurrentProfiles) {
+            mCurrentProfiles.clear();
+            if (mUserManager != null) {
+                for (UserInfo user : mUserManager.getProfiles(mCurrentUserId)) {
+                    mCurrentProfiles.put(user.id, user);
+                }
+            }
+        }
+    }
+
+    protected void notifyUserAboutHiddenNotifications() {
+        if (0 != Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 1)) {
+            Log.d(TAG, "user hasn't seen notification about hidden notifications");
+            if (!mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) {
+                Log.d(TAG, "insecure lockscreen, skipping notification");
+                Settings.Secure.putInt(mContext.getContentResolver(),
+                        Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0);
+                return;
+            }
+            Log.d(TAG, "disabling lockecreen notifications and alerting the user");
+            // disable lockscreen notifications until user acts on the banner.
+            Settings.Secure.putInt(mContext.getContentResolver(),
+                    Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0);
+            Settings.Secure.putInt(mContext.getContentResolver(),
+                    Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0);
+
+            final String packageName = mContext.getPackageName();
+            PendingIntent cancelIntent = PendingIntent.getBroadcast(mContext, 0,
+                    new Intent(BANNER_ACTION_CANCEL).setPackage(packageName),
+                    PendingIntent.FLAG_CANCEL_CURRENT);
+            PendingIntent setupIntent = PendingIntent.getBroadcast(mContext, 0,
+                    new Intent(BANNER_ACTION_SETUP).setPackage(packageName),
+                    PendingIntent.FLAG_CANCEL_CURRENT);
+
+            final int colorRes = com.android.internal.R.color.system_notification_accent_color;
+            Notification.Builder note = new Notification.Builder(mContext)
+                    .setSmallIcon(R.drawable.ic_android)
+                    .setContentTitle(mContext.getString(R.string.hidden_notifications_title))
+                    .setContentText(mContext.getString(R.string.hidden_notifications_text))
+                    .setChannel(NotificationChannels.SECURITY)
+                    .setOngoing(true)
+                    .setColor(mContext.getColor(colorRes))
+                    .setContentIntent(setupIntent)
+                    .addAction(R.drawable.ic_close,
+                            mContext.getString(R.string.hidden_notifications_cancel),
+                            cancelIntent)
+                    .addAction(R.drawable.ic_settings,
+                            mContext.getString(R.string.hidden_notifications_setup),
+                            setupIntent);
+            overrideNotificationAppName(mContext, note);
+
+            NotificationManager noMan =
+                    (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+            noMan.notify(SystemMessage.NOTE_HIDDEN_NOTIFICATIONS, note.build());
+        }
+    }
+
+    @Override  // NotificationData.Environment
+    public boolean isNotificationForCurrentProfiles(StatusBarNotification n) {
+        final int thisUserId = mCurrentUserId;
+        final int notificationUserId = n.getUserId();
+        if (DEBUG && MULTIUSER_DEBUG) {
+            Log.v(TAG, String.format("%s: current userid: %d, notification userid: %d",
+                    n, thisUserId, notificationUserId));
+        }
+        return isCurrentProfile(notificationUserId);
+    }
+
+    protected void setNotificationShown(StatusBarNotification n) {
+        setNotificationsShown(new String[]{n.getKey()});
+    }
+
+    protected void setNotificationsShown(String[] keys) {
+        try {
+            mNotificationListener.setNotificationsShown(keys);
+        } catch (RuntimeException e) {
+            Log.d(TAG, "failed setNotificationsShown: ", e);
+        }
+    }
+
+    protected boolean isCurrentProfile(int userId) {
+        synchronized (mCurrentProfiles) {
+            return userId == UserHandle.USER_ALL || mCurrentProfiles.get(userId) != null;
+        }
+    }
+
+    @Override
+    public NotificationGroupManager getGroupManager() {
+        return mGroupManager;
+    }
+
+    protected void bindDismissRunnable(final ExpandableNotificationRow row) {
+        row.setOnDismissRunnable(() -> performRemoveNotification(row.getStatusBarNotification()));
+    }
+
+    protected void applyColorsAndBackgrounds(StatusBarNotification sbn,
+            NotificationData.Entry entry) {
+
+        if (entry.getContentView().getId()
+                != com.android.internal.R.id.status_bar_latest_event_content) {
+            // Using custom RemoteViews
+            if (entry.targetSdk >= Build.VERSION_CODES.GINGERBREAD
+                    && entry.targetSdk < Build.VERSION_CODES.LOLLIPOP) {
+                entry.row.setShowingLegacyBackground(true);
+                entry.legacy = true;
+            }
+        }
+
+        entry.setIconTag(R.id.icon_is_pre_L, entry.targetSdk < Build.VERSION_CODES.LOLLIPOP);
+    }
+
+    public boolean isMediaNotification(NotificationData.Entry entry) {
+        // TODO: confirm that there's a valid media key
+        return entry.getExpandedContentView() != null &&
+               entry.getExpandedContentView()
+                       .findViewById(com.android.internal.R.id.media_actions) != null;
+    }
+
+    // The (i) button in the guts that links to the system notification settings for that app
+    private void startAppNotificationSettingsActivity(String packageName, final int appUid) {
+        final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
+        intent.putExtra(Settings.EXTRA_APP_PACKAGE, packageName);
+        intent.putExtra(Settings.EXTRA_APP_UID, appUid);
+        startNotificationGutsIntent(intent, appUid);
+    }
+
+    private void startNotificationGutsIntent(final Intent intent, final int appUid) {
+        dismissKeyguardThenExecute(new OnDismissAction() {
+            @Override
+            public boolean onDismiss() {
+                AsyncTask.execute(new Runnable() {
+                    @Override
+                    public void run() {
+                        TaskStackBuilder.create(mContext)
+                                .addNextIntentWithParentStack(intent)
+                                .startActivities(getActivityOptions(),
+                                        new UserHandle(UserHandle.getUserId(appUid)));
+                    }
+                });
+                animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
+                return true;
+            }
+        }, false /* afterKeyguardGone */);
+    }
+
+    protected void setNotificationSnoozed(StatusBarNotification sbn, SnoozeOption snoozeOption) {
+        if (snoozeOption.criterion != null) {
+            mNotificationListener.snoozeNotification(sbn.getKey(), snoozeOption.criterion.getId());
+        } else {
+            GregorianCalendar snoozeUntil = new GregorianCalendar();
+            snoozeUntil.add(Calendar.MINUTE, snoozeOption.snoozeForMinutes);
+            mNotificationListener.snoozeNotification(sbn.getKey(), snoozeUntil.getTimeInMillis());
+        }
+    }
+
+    private void bindGuts(final ExpandableNotificationRow row, MenuItem item) {
+        row.inflateGuts();
+        row.setGutsView(item);
+        final StatusBarNotification sbn = row.getStatusBarNotification();
+        row.setTag(sbn.getPackageName());
+        final NotificationGuts guts = row.getGuts();
+        guts.setClosedListener((NotificationGuts g) -> {
+            if (!row.isRemoved()) {
+                mStackScroller.onHeightChanged(row, !isPanelFullyCollapsed() /* needsAnimation */);
+            }
+            mNotificationGutsExposed = null;
+            mGutsMenuItem = null;
+        });
+
+        if (item.gutsContent instanceof SnoozeGutsContent) {
+            ((SnoozeGutsContent) item.gutsContent).setSnoozeListener(getSnoozeListener());
+            ((SnoozeGutsContent) item.gutsContent).setStatusBarNotification(sbn);
+            ((NotificationSnooze) item.gutsContent).setSnoozeOptions(row.getEntry().snoozeCriteria);
+        }
+
+        if (item.gutsContent instanceof NotificationInfo) {
+            final NotificationChannel channel = row.getEntry().channel;
+            PackageManager pmUser = getPackageManagerForUser(mContext,
+                    sbn.getUser().getIdentifier());
+            final INotificationManager iNotificationManager = INotificationManager.Stub.asInterface(
+                    ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+            final String pkg = sbn.getPackageName();
+            NotificationInfo info = (NotificationInfo) item.gutsContent;
+            final NotificationInfo.OnSettingsClickListener onSettingsClick = (View v,
+                    int appUid) -> {
+                MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_INFO);
+                guts.resetFalsingCheck();
+                startAppNotificationSettingsActivity(pkg, appUid);
+            };
+            final View.OnClickListener onDoneClick = (View v) -> {
+                // If the user has security enabled, show challenge if the setting is changed.
+                if (info.hasImportanceChanged()
+                        && isLockscreenPublicMode(sbn.getUser().getIdentifier())
+                        && (mState == StatusBarState.KEYGUARD
+                                || mState == StatusBarState.SHADE_LOCKED)) {
+                    OnDismissAction dismissAction = new OnDismissAction() {
+                        @Override
+                        public boolean onDismiss() {
+                            saveAndCloseNotificationMenu(info, row, guts, v);
+                            return true;
+                        }
+                    };
+                    onLockedNotificationImportanceChange(dismissAction);
+                } else {
+                    saveAndCloseNotificationMenu(info, row, guts, v);
+                }
+            };
+            info.bindNotification(pmUser, iNotificationManager, sbn, channel, onSettingsClick,
+                    onDoneClick,
+                    mNonBlockablePkgs);
+        }
+    }
+
+    private void saveAndCloseNotificationMenu(NotificationInfo info,
+            ExpandableNotificationRow row, NotificationGuts guts, View done) {
+        guts.resetFalsingCheck();
+        info.saveImportance();
+        int[] rowLocation = new int[2];
+        int[] doneLocation = new int[2];
+        row.getLocationOnScreen(rowLocation);
+        done.getLocationOnScreen(doneLocation);
+
+        final int centerX = done.getWidth() / 2;
+        final int centerY = done.getHeight() / 2;
+        final int x = doneLocation[0] - rowLocation[0] + centerX;
+        final int y = doneLocation[1] - rowLocation[1] + centerY;
+        dismissPopups(x, y);
+    }
+
+    protected SwipeHelper.LongPressListener getNotificationLongClicker() {
+        return new SwipeHelper.LongPressListener() {
+            @Override
+            public boolean onLongPress(View v, final int x, final int y,
+                    MenuItem item) {
+                if (!(v instanceof ExpandableNotificationRow)) {
+                    return false;
+                }
+                if (v.getWindowToken() == null) {
+                    Log.e(TAG, "Trying to show notification guts, but not attached to window");
+                    return false;
+                }
+
+                final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+                bindGuts(row, item);
+                NotificationGuts guts = row.getGuts();
+
+                // Assume we are a status_bar_notification_row
+                if (guts == null) {
+                    // This view has no guts. Examples are the more card or the dismiss all view
+                    return false;
+                }
+
+                // Already showing?
+                if (guts.getVisibility() == View.VISIBLE) {
+                    dismissPopups(x, y);
+                    return false;
+                }
+
+                MetricsLogger.action(mContext, MetricsEvent.ACTION_NOTE_CONTROLS);
+
+                // ensure that it's laid but not visible until actually laid out
+                guts.setVisibility(View.INVISIBLE);
+                // Post to ensure the the guts are properly laid out.
+                guts.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        if (row.getWindowToken() == null) {
+                            Log.e(TAG, "Trying to show notification guts, but not attached to "
+                                    + "window");
+                            return;
+                        }
+                        dismissPopups(-1 /* x */, -1 /* y */, false /* resetGear */,
+                                false /* animate */);
+                        guts.setVisibility(View.VISIBLE);
+                        final double horz = Math.max(guts.getWidth() - x, x);
+                        final double vert = Math.max(guts.getHeight() - y, y);
+                        final float r = (float) Math.hypot(horz, vert);
+                        final Animator a
+                                = ViewAnimationUtils.createCircularReveal(guts, x, y, 0, r);
+                        a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+                        a.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+                        a.addListener(new AnimatorListenerAdapter() {
+                            @Override
+                            public void onAnimationEnd(Animator animation) {
+                                super.onAnimationEnd(animation);
+                                // Move the notification view back over the gear
+                                row.resetTranslation();
+                            }
+                        });
+                        a.start();
+                        guts.setExposed(true /* exposed */,
+                                mState == StatusBarState.KEYGUARD /* needsFalsingProtection */);
+                        row.closeRemoteInput();
+                        mStackScroller.onHeightChanged(row, true /* needsAnimation */);
+                        mNotificationGutsExposed = guts;
+                        mGutsMenuItem = item;
+                    }
+                });
+                return true;
+            }
+        };
+    }
+
+    /**
+     * Returns the exposed NotificationGuts or null if none are exposed.
+     */
+    public NotificationGuts getExposedGuts() {
+        return mNotificationGutsExposed;
+    }
+
+    public void dismissPopups() {
+        dismissPopups(-1 /* x */, -1 /* y */, true /* resetGear */, false /* animate */);
+    }
+
+    private void dismissPopups(int x, int y) {
+        dismissPopups(x, y, true /* resetGear */, false /* animate */);
+    }
+
+    public void dismissPopups(int x, int y, boolean resetGear, boolean animate) {
+        if (mNotificationGutsExposed != null) {
+            mNotificationGutsExposed.closeControls(x, y, true /* save */);
+        }
+        if (resetGear) {
+            mStackScroller.resetExposedGearView(animate, true /* force */);
+        }
+    }
+
+    @Override
+    public void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
+        int msg = MSG_SHOW_RECENT_APPS;
+        mHandler.removeMessages(msg);
+        mHandler.obtainMessage(msg, triggeredFromAltTab ? 1 : 0, fromHome ? 1 : 0).sendToTarget();
+    }
+
+    @Override
+    public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
+        int msg = MSG_HIDE_RECENT_APPS;
+        mHandler.removeMessages(msg);
+        mHandler.obtainMessage(msg, triggeredFromAltTab ? 1 : 0,
+                triggeredFromHomeKey ? 1 : 0).sendToTarget();
+    }
+
+    @Override
+    public void toggleRecentApps() {
+        toggleRecents();
+    }
+
+    @Override
+    public void toggleSplitScreen() {
+        toggleSplitScreenMode(-1 /* metricsDockAction */, -1 /* metricsUndockAction */);
+    }
+
+    @Override
+    public void preloadRecentApps() {
+        int msg = MSG_PRELOAD_RECENT_APPS;
+        mHandler.removeMessages(msg);
+        mHandler.sendEmptyMessage(msg);
+    }
+
+    @Override
+    public void cancelPreloadRecentApps() {
+        int msg = MSG_CANCEL_PRELOAD_RECENT_APPS;
+        mHandler.removeMessages(msg);
+        mHandler.sendEmptyMessage(msg);
+    }
+
+    @Override
+    public void dismissKeyboardShortcutsMenu() {
+        int msg = MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU;
+        mHandler.removeMessages(msg);
+        mHandler.sendEmptyMessage(msg);
+    }
+
+    @Override
+    public void toggleKeyboardShortcutsMenu(int deviceId) {
+        int msg = MSG_TOGGLE_KEYBOARD_SHORTCUTS_MENU;
+        mHandler.removeMessages(msg);
+        mHandler.obtainMessage(msg, deviceId, 0).sendToTarget();
+    }
+
+    /** Jumps to the next affiliated task in the group. */
+    public void showNextAffiliatedTask() {
+        int msg = MSG_SHOW_NEXT_AFFILIATED_TASK;
+        mHandler.removeMessages(msg);
+        mHandler.sendEmptyMessage(msg);
+    }
+
+    /** Jumps to the previous affiliated task in the group. */
+    public void showPreviousAffiliatedTask() {
+        int msg = MSG_SHOW_PREV_AFFILIATED_TASK;
+        mHandler.removeMessages(msg);
+        mHandler.sendEmptyMessage(msg);
+    }
+
+    protected void sendCloseSystemWindows(String reason) {
+        try {
+            ActivityManager.getService().closeSystemDialogs(reason);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /** Proxy for RecentsComponent */
+
+    protected void showRecents(boolean triggeredFromAltTab, boolean fromHome) {
+        if (mRecents != null) {
+            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
+            mRecents.showRecents(triggeredFromAltTab, fromHome);
+        }
+    }
+
+    protected void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
+        if (mRecents != null) {
+            mRecents.hideRecents(triggeredFromAltTab, triggeredFromHomeKey);
+        }
+    }
+
+    protected void toggleRecents() {
+        if (mRecents != null) {
+            mRecents.toggleRecents(mDisplay);
+        }
+    }
+
+    protected void preloadRecents() {
+        if (mRecents != null) {
+            mRecents.preloadRecents();
+        }
+    }
+
+    protected void toggleKeyboardShortcuts(int deviceId) {
+        KeyboardShortcuts.toggle(mContext, deviceId);
+    }
+
+    protected void dismissKeyboardShortcuts() {
+        KeyboardShortcuts.dismiss();
+    }
+
+    protected void cancelPreloadingRecents() {
+        if (mRecents != null) {
+            mRecents.cancelPreloadingRecents();
+        }
+    }
+
+    protected void showRecentsNextAffiliatedTask() {
+        if (mRecents != null) {
+            mRecents.showNextAffiliatedTask();
+        }
+    }
+
+    protected void showRecentsPreviousAffiliatedTask() {
+        if (mRecents != null) {
+            mRecents.showPrevAffiliatedTask();
+        }
+    }
+
+    /**
+     * Save the current "public" (locked and secure) state of the lockscreen.
+     */
+    public void setLockscreenPublicMode(boolean publicMode, int userId) {
+        mLockscreenPublicMode.put(userId, publicMode);
+    }
+
+    public boolean isLockscreenPublicMode(int userId) {
+        return mLockscreenPublicMode.get(userId, false);
+    }
+
+    /**
+     * Has the given user chosen to allow notifications to be shown even when the lockscreen is in
+     * "public" (secure & locked) mode?
+     */
+    public boolean userAllowsNotificationsInPublic(int userHandle) {
+        if (userHandle == UserHandle.USER_ALL) {
+            return true;
+        }
+
+        if (mUsersAllowingNotifications.indexOfKey(userHandle) < 0) {
+            final boolean allowed = 0 != Settings.Secure.getIntForUser(
+                    mContext.getContentResolver(),
+                    Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, userHandle);
+            mUsersAllowingNotifications.append(userHandle, allowed);
+            return allowed;
+        }
+
+        return mUsersAllowingNotifications.get(userHandle);
+    }
+
+    /**
+     * Has the given user chosen to allow their private (full) notifications to be shown even
+     * when the lockscreen is in "public" (secure & locked) mode?
+     */
+    public boolean userAllowsPrivateNotificationsInPublic(int userHandle) {
+        if (userHandle == UserHandle.USER_ALL) {
+            return true;
+        }
+
+        if (mUsersAllowingPrivateNotifications.indexOfKey(userHandle) < 0) {
+            final boolean allowedByUser = 0 != Settings.Secure.getIntForUser(
+                    mContext.getContentResolver(),
+                    Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, userHandle);
+            final boolean allowedByDpm = adminAllowsUnredactedNotifications(userHandle);
+            final boolean allowed = allowedByUser && allowedByDpm;
+            mUsersAllowingPrivateNotifications.append(userHandle, allowed);
+            return allowed;
+        }
+
+        return mUsersAllowingPrivateNotifications.get(userHandle);
+    }
+
+    private boolean adminAllowsUnredactedNotifications(int userHandle) {
+        if (userHandle == UserHandle.USER_ALL) {
+            return true;
+        }
+        final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures(null /* admin */,
+                    userHandle);
+        return (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) == 0;
+    }
+
+    /**
+     * Returns true if we're on a secure lockscreen and the user wants to hide notification data.
+     * If so, notifications should be hidden.
+     */
+    @Override  // NotificationData.Environment
+    public boolean shouldHideNotifications(int userId) {
+        return isLockscreenPublicMode(userId) && !userAllowsNotificationsInPublic(userId)
+                || (userId != mCurrentUserId && shouldHideNotifications(mCurrentUserId));
+    }
+
+    /**
+     * Returns true if we're on a secure lockscreen and the user wants to hide notifications via
+     * package-specific override.
+     */
+    @Override // NotificationDate.Environment
+    public boolean shouldHideNotifications(String key) {
+        return isLockscreenPublicMode(mCurrentUserId)
+                && mNotificationData.getVisibilityOverride(key) == Notification.VISIBILITY_SECRET;
+    }
+
+    /**
+     * Returns true if we're on a secure lockscreen.
+     */
+    @Override  // NotificationData.Environment
+    public boolean isSecurelyLocked(int userId) {
+        return isLockscreenPublicMode(userId);
+    }
+
+    public void onNotificationClear(StatusBarNotification notification) {
+        try {
+            mBarService.onNotificationClear(
+                    notification.getPackageName(),
+                    notification.getTag(),
+                    notification.getId(),
+                    notification.getUserId());
+        } catch (android.os.RemoteException ex) {
+            // oh well
+        }
+    }
+
+    /**
+     * Called when the notification panel layouts
+     */
+    public void onPanelLaidOut() {
+        if (mState == StatusBarState.KEYGUARD) {
+            // Since the number of notifications is determined based on the height of the view, we
+            // need to update them.
+            int maxBefore = getMaxKeyguardNotifications(false /* recompute */);
+            int maxNotifications = getMaxKeyguardNotifications(true /* recompute */);
+            if (maxBefore != maxNotifications) {
+                updateRowStates();
+            }
+        }
+    }
+
+    protected boolean inflateViews(Entry entry, ViewGroup parent) {
+        PackageManager pmUser = getPackageManagerForUser(mContext,
+                entry.notification.getUser().getIdentifier());
+
+        final StatusBarNotification sbn = entry.notification;
+        boolean isLowPriority = mNotificationData.isAmbient(sbn.getKey());
+        try {
+            entry.cacheContentViews(mContext, null, isLowPriority);
+        } catch (RuntimeException e) {
+            Log.e(TAG, "Unable to get notification remote views", e);
+            return false;
+        }
+
+        final RemoteViews contentView = entry.cachedContentView;
+        final RemoteViews bigContentView = entry.cachedBigContentView;
+        final RemoteViews headsUpContentView = entry.cachedHeadsUpContentView;
+        final RemoteViews publicContentView = entry.cachedPublicContentView;
+        final RemoteViews ambientContentView = entry.cachedAmbientContentView;
+
+        if (contentView == null) {
+            Log.v(TAG, "no contentView for: " + sbn.getNotification());
+            return false;
+        }
+
+        if (DEBUG) {
+            Log.v(TAG, "publicContentView: " + publicContentView);
+        }
+
+        ExpandableNotificationRow row;
+
+        // Stash away previous user expansion state so we can restore it at
+        // the end.
+        boolean hasUserChangedExpansion = false;
+        boolean userExpanded = false;
+        boolean userLocked = false;
+
+        if (entry.row != null) {
+            row = entry.row;
+            hasUserChangedExpansion = row.hasUserChangedExpansion();
+            userExpanded = row.isUserExpanded();
+            userLocked = row.isUserLocked();
+            entry.reset();
+            if (hasUserChangedExpansion) {
+                row.setUserExpanded(userExpanded);
+            }
+        } else {
+            // create the row view
+            LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
+                    Context.LAYOUT_INFLATER_SERVICE);
+            row = (ExpandableNotificationRow) inflater.inflate(R.layout.status_bar_notification_row,
+                    parent, false);
+            row.setExpansionLogger(this, entry.notification.getKey());
+            row.setGroupManager(mGroupManager);
+            row.setHeadsUpManager(mHeadsUpManager);
+            row.setRemoteInputController(mRemoteInputController);
+            row.setOnExpandClickListener(this);
+
+            // Get the app name.
+            // Note that Notification.Builder#bindHeaderAppName has similar logic
+            // but since this field is used in the guts, it must be accurate.
+            // Therefore we will only show the application label, or, failing that, the
+            // package name. No substitutions.
+            final String pkg = sbn.getPackageName();
+            String appname = pkg;
+            try {
+                final ApplicationInfo info = pmUser.getApplicationInfo(pkg,
+                        PackageManager.MATCH_UNINSTALLED_PACKAGES
+                                | PackageManager.MATCH_DISABLED_COMPONENTS);
+                if (info != null) {
+                    appname = String.valueOf(pmUser.getApplicationLabel(info));
+                }
+            } catch (NameNotFoundException e) {
+                // Do nothing
+            }
+            row.setAppName(appname);
+        }
+
+        bindDismissRunnable(row);
+        row.setIsLowPriority(isLowPriority);
+
+        // NB: the large icon is now handled entirely by the template
+
+        // bind the click event to the content area
+        NotificationContentView contentContainer = row.getPrivateLayout();
+        NotificationContentView contentContainerPublic = row.getPublicLayout();
+
+        row.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
+        if (ENABLE_REMOTE_INPUT) {
+            row.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
+        }
+
+        mNotificationClicker.register(row, sbn);
+
+        // set up the adaptive layout
+        View contentViewLocal = null;
+        View bigContentViewLocal = null;
+        View headsUpContentViewLocal = null;
+        View publicViewLocal = null;
+        View ambientViewLocal = null;
+        try {
+            contentViewLocal = contentView.apply(
+                    sbn.getPackageContext(mContext),
+                    contentContainer,
+                    mOnClickHandler);
+            if (bigContentView != null) {
+                bigContentViewLocal = bigContentView.apply(
+                        sbn.getPackageContext(mContext),
+                        contentContainer,
+                        mOnClickHandler);
+            }
+            if (headsUpContentView != null) {
+                headsUpContentViewLocal = headsUpContentView.apply(
+                        sbn.getPackageContext(mContext),
+                        contentContainer,
+                        mOnClickHandler);
+            }
+            if (publicContentView != null) {
+                publicViewLocal = publicContentView.apply(
+                        sbn.getPackageContext(mContext),
+                        contentContainerPublic, mOnClickHandler);
+            }
+            if (ambientContentView != null) {
+                ambientViewLocal = ambientContentView.apply(
+                        sbn.getPackageContext(mContext),
+                        contentContainer, mOnClickHandler);
+            }
+
+            if (contentViewLocal != null) {
+                contentViewLocal.setIsRootNamespace(true);
+                contentContainer.setContractedChild(contentViewLocal);
+            }
+            if (bigContentViewLocal != null) {
+                bigContentViewLocal.setIsRootNamespace(true);
+                contentContainer.setExpandedChild(bigContentViewLocal);
+            }
+            if (headsUpContentViewLocal != null) {
+                headsUpContentViewLocal.setIsRootNamespace(true);
+                contentContainer.setHeadsUpChild(headsUpContentViewLocal);
+            }
+            if (publicViewLocal != null) {
+                publicViewLocal.setIsRootNamespace(true);
+                contentContainerPublic.setContractedChild(publicViewLocal);
+            }
+
+            if (ambientViewLocal != null) {
+                ambientViewLocal.setIsRootNamespace(true);
+                contentContainer.setAmbientChild(ambientViewLocal);
+            }
+        }
+        catch (RuntimeException e) {
+            final String ident = sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId());
+            Log.e(TAG, "couldn't inflate view for notification " + ident, e);
+            return false;
+        }
+
+        // Extract target SDK version.
+        try {
+            ApplicationInfo info = pmUser.getApplicationInfo(sbn.getPackageName(), 0);
+            entry.targetSdk = info.targetSdkVersion;
+        } catch (NameNotFoundException ex) {
+            Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex);
+        }
+        entry.autoRedacted = entry.notification.getNotification().publicVersion == null;
+
+        entry.row = row;
+        entry.row.setOnActivatedListener(this);
+        entry.row.setExpandable(bigContentViewLocal != null);
+
+        applyColorsAndBackgrounds(sbn, entry);
+
+        // Restore previous flags.
+        if (hasUserChangedExpansion) {
+            // Note: setUserExpanded() conveniently ignores calls with
+            //       userExpanded=true if !isExpandable().
+            row.setUserExpanded(userExpanded);
+        }
+        row.setUserLocked(userLocked);
+        row.onNotificationUpdated(entry);
+        return true;
+    }
+
+    /**
+     * Adds RemoteInput actions from the WearableExtender; to be removed once more apps support this
+     * via first-class API.
+     *
+     * TODO: Remove once enough apps specify remote inputs on their own.
+     */
+    private void processForRemoteInput(Notification n) {
+        if (!ENABLE_REMOTE_INPUT) return;
+
+        if (n.extras != null && n.extras.containsKey("android.wearable.EXTENSIONS") &&
+                (n.actions == null || n.actions.length == 0)) {
+            Notification.Action viableAction = null;
+            Notification.WearableExtender we = new Notification.WearableExtender(n);
+
+            List<Notification.Action> actions = we.getActions();
+            final int numActions = actions.size();
+
+            for (int i = 0; i < numActions; i++) {
+                Notification.Action action = actions.get(i);
+                if (action == null) {
+                    continue;
+                }
+                RemoteInput[] remoteInputs = action.getRemoteInputs();
+                if (remoteInputs == null) {
+                    continue;
+                }
+                for (RemoteInput ri : remoteInputs) {
+                    if (ri.getAllowFreeFormInput()) {
+                        viableAction = action;
+                        break;
+                    }
+                }
+                if (viableAction != null) {
+                    break;
+                }
+            }
+
+            if (viableAction != null) {
+                Notification.Builder rebuilder = Notification.Builder.recoverBuilder(mContext, n);
+                rebuilder.setActions(viableAction);
+                rebuilder.build(); // will rewrite n
+            }
+        }
+    }
+
+    public void startPendingIntentDismissingKeyguard(final PendingIntent intent) {
+        if (!isDeviceProvisioned()) return;
+
+        final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
+        final boolean afterKeyguardGone = intent.isActivity()
+                && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
+                mCurrentUserId);
+        dismissKeyguardThenExecute(new OnDismissAction() {
+            @Override
+            public boolean onDismiss() {
+                new Thread() {
+                    @Override
+                    public void run() {
+                        try {
+                            // The intent we are sending is for the application, which
+                            // won't have permission to immediately start an activity after
+                            // the user switches to home.  We know it is safe to do at this
+                            // point, so make sure new activity switches are now allowed.
+                            ActivityManager.getService().resumeAppSwitches();
+                        } catch (RemoteException e) {
+                        }
+                        try {
+                            intent.send(null, 0, null, null, null, null, getActivityOptions());
+                        } catch (PendingIntent.CanceledException e) {
+                            // the stack trace isn't very helpful here.
+                            // Just log the exception message.
+                            Log.w(TAG, "Sending intent failed: " + e);
+
+                            // TODO: Dismiss Keyguard.
+                        }
+                        if (intent.isActivity()) {
+                            mAssistManager.hideAssist();
+                        }
+                    }
+                }.start();
+
+                // close the shade if it was open
+                animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
+                        true /* force */, true /* delayed */);
+                visibilityChanged(false);
+
+                return true;
+            }
+        }, afterKeyguardGone);
+    }
+
+
+    private final class NotificationClicker implements View.OnClickListener {
+
+        @Override
+        public void onClick(final View v) {
+            if (!(v instanceof ExpandableNotificationRow)) {
+                Log.e(TAG, "NotificationClicker called on a view that is not a notification row.");
+                return;
+            }
+
+            wakeUpIfDozing(SystemClock.uptimeMillis(), v);
+
+            final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+            final StatusBarNotification sbn = row.getStatusBarNotification();
+            if (sbn == null) {
+                Log.e(TAG, "NotificationClicker called on an unclickable notification,");
+                return;
+            }
+
+            // Check if the notification is displaying the gear, if so slide notification back
+            if (row.getSettingsRow() != null && row.getSettingsRow().isVisible()) {
+                row.animateTranslateNotification(0);
+                return;
+            }
+
+            Notification notification = sbn.getNotification();
+            final PendingIntent intent = notification.contentIntent != null
+                    ? notification.contentIntent
+                    : notification.fullScreenIntent;
+            final String notificationKey = sbn.getKey();
+
+            // Mark notification for one frame.
+            row.setJustClicked(true);
+            DejankUtils.postAfterTraversal(new Runnable() {
+                @Override
+                public void run() {
+                    row.setJustClicked(false);
+                }
+            });
+
+            final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
+            final boolean afterKeyguardGone = intent.isActivity()
+                    && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
+                            mCurrentUserId);
+            dismissKeyguardThenExecute(new OnDismissAction() {
+                @Override
+                public boolean onDismiss() {
+                    if (mHeadsUpManager != null && mHeadsUpManager.isHeadsUp(notificationKey)) {
+                        // Release the HUN notification to the shade.
+
+                        if (isPanelFullyCollapsed()) {
+                            HeadsUpManager.setIsClickedNotification(row, true);
+                        }
+                        //
+                        // In most cases, when FLAG_AUTO_CANCEL is set, the notification will
+                        // become canceled shortly by NoMan, but we can't assume that.
+                        mHeadsUpManager.releaseImmediately(notificationKey);
+                    }
+                    StatusBarNotification parentToCancel = null;
+                    if (shouldAutoCancel(sbn) && mGroupManager.isOnlyChildInGroup(sbn)) {
+                        StatusBarNotification summarySbn = mGroupManager.getLogicalGroupSummary(sbn)
+                                        .getStatusBarNotification();
+                        if (shouldAutoCancel(summarySbn)) {
+                            parentToCancel = summarySbn;
+                        }
+                    }
+                    final StatusBarNotification parentToCancelFinal = parentToCancel;
+                    new Thread() {
+                        @Override
+                        public void run() {
+                            try {
+                                // The intent we are sending is for the application, which
+                                // won't have permission to immediately start an activity after
+                                // the user switches to home.  We know it is safe to do at this
+                                // point, so make sure new activity switches are now allowed.
+                                ActivityManager.getService().resumeAppSwitches();
+                            } catch (RemoteException e) {
+                            }
+                            if (intent != null) {
+                                // If we are launching a work activity and require to launch
+                                // separate work challenge, we defer the activity action and cancel
+                                // notification until work challenge is unlocked.
+                                if (intent.isActivity()) {
+                                    final int userId = intent.getCreatorUserHandle()
+                                            .getIdentifier();
+                                    if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
+                                            && mKeyguardManager.isDeviceLocked(userId)) {
+                                        boolean canBypass = false;
+                                        try {
+                                            canBypass = ActivityManager.getService()
+                                                    .canBypassWorkChallenge(intent);
+                                        } catch (RemoteException e) {
+                                        }
+                                        // For direct-boot aware activities, they can be shown when
+                                        // the device is still locked without triggering the work
+                                        // challenge.
+                                        if ((!canBypass) && startWorkChallengeIfNecessary(userId,
+                                                    intent.getIntentSender(), notificationKey)) {
+                                            // Show work challenge, do not run PendingIntent and
+                                            // remove notification
+                                            return;
+                                        }
+                                    }
+                                }
+                                try {
+                                    intent.send(null, 0, null, null, null, null,
+                                            getActivityOptions());
+                                } catch (PendingIntent.CanceledException e) {
+                                    // the stack trace isn't very helpful here.
+                                    // Just log the exception message.
+                                    Log.w(TAG, "Sending contentIntent failed: " + e);
+
+                                    // TODO: Dismiss Keyguard.
+                                }
+                                if (intent.isActivity()) {
+                                    mAssistManager.hideAssist();
+                                }
+                            }
+
+                            try {
+                                mBarService.onNotificationClick(notificationKey);
+                            } catch (RemoteException ex) {
+                                // system process is dead if we're here.
+                            }
+                            if (parentToCancelFinal != null) {
+                                // We have to post it to the UI thread for synchronization
+                                mHandler.post(new Runnable() {
+                                    @Override
+                                    public void run() {
+                                        Runnable removeRunnable = new Runnable() {
+                                            @Override
+                                            public void run() {
+                                                performRemoveNotification(parentToCancelFinal);
+                                            }
+                                        };
+                                        if (isCollapsing()) {
+                                            // To avoid lags we're only performing the remove
+                                            // after the shade was collapsed
+                                            addPostCollapseAction(removeRunnable);
+                                        } else {
+                                            removeRunnable.run();
+                                        }
+                                    }
+                                });
+                            }
+                        }
+                    }.start();
+
+                    // close the shade if it was open
+                    animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
+                            true /* force */, true /* delayed */);
+                    visibilityChanged(false);
+
+                    return true;
+                }
+            }, afterKeyguardGone);
+        }
+
+        private boolean shouldAutoCancel(StatusBarNotification sbn) {
+            int flags = sbn.getNotification().flags;
+            if ((flags & Notification.FLAG_AUTO_CANCEL) != Notification.FLAG_AUTO_CANCEL) {
+                return false;
+            }
+            if ((flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
+                return false;
+            }
+            return true;
+        }
+
+        public void register(ExpandableNotificationRow row, StatusBarNotification sbn) {
+            Notification notification = sbn.getNotification();
+            if (notification.contentIntent != null || notification.fullScreenIntent != null) {
+                row.setOnClickListener(this);
+            } else {
+                row.setOnClickListener(null);
+            }
+        }
+    }
+
+    protected Bundle getActivityOptions() {
+        // Anything launched from the notification shade should always go into the
+        // fullscreen stack.
+        ActivityOptions options = ActivityOptions.makeBasic();
+        options.setLaunchStackId(StackId.FULLSCREEN_WORKSPACE_STACK_ID);
+        return options.toBundle();
+    }
+
+    protected void visibilityChanged(boolean visible) {
+        if (mVisible != visible) {
+            mVisible = visible;
+            if (!visible) {
+                dismissPopups();
+            }
+        }
+        updateVisibleToUser();
+    }
+
+    protected void updateVisibleToUser() {
+        boolean oldVisibleToUser = mVisibleToUser;
+        mVisibleToUser = mVisible && mDeviceInteractive;
+
+        if (oldVisibleToUser != mVisibleToUser) {
+            handleVisibleToUserChanged(mVisibleToUser);
+        }
+    }
+
+    /**
+     * Clear Buzz/Beep/Blink.
+     */
+    public void clearNotificationEffects() {
+        try {
+            mBarService.clearNotificationEffects();
+        } catch (RemoteException e) {
+            // Won't fail unless the world has ended.
+        }
+    }
+
+    /**
+     * Cancel this notification and tell the StatusBarManagerService / NotificationManagerService
+     * about the failure.
+     *
+     * WARNING: this will call back into us.  Don't hold any locks.
+     */
+    void handleNotificationError(StatusBarNotification n, String message) {
+        removeNotification(n.getKey(), null);
+        try {
+            mBarService.onNotificationError(n.getPackageName(), n.getTag(), n.getId(), n.getUid(),
+                    n.getInitialPid(), message, n.getUserId());
+        } catch (RemoteException ex) {
+            // The end is nigh.
+        }
+    }
+
+    protected StatusBarNotification removeNotificationViews(String key, RankingMap ranking) {
+        NotificationData.Entry entry = mNotificationData.remove(key, ranking);
+        if (entry == null) {
+            Log.w(TAG, "removeNotification for unknown key: " + key);
+            return null;
+        }
+        updateNotifications();
+        return entry.notification;
+    }
+
+    protected NotificationData.Entry createNotificationViews(StatusBarNotification sbn) {
+        if (DEBUG) {
+            Log.d(TAG, "createNotificationViews(notification=" + sbn);
+        }
+        NotificationData.Entry entry = new NotificationData.Entry(sbn);
+        try {
+            entry.createIcons(mContext, sbn);
+        } catch (NotificationData.IconException exception) {
+            handleNotificationError(sbn, exception.getMessage());
+        }
+
+        // Construct the expanded view.
+        if (!inflateViews(entry, mStackScroller)) {
+            handleNotificationError(sbn, "Couldn't expand RemoteViews for: " + sbn);
+            return null;
+        }
+        return entry;
+    }
+
+    protected void addNotificationViews(Entry entry, RankingMap ranking) {
+        if (entry == null) {
+            return;
+        }
+        // Add the expanded view and icon.
+        mNotificationData.add(entry, ranking);
+        updateNotifications();
+    }
+
+    /**
+     * Updates expanded, dimmed and locked states of notification rows.
+     */
+    protected void updateRowStates() {
+        final int N = mStackScroller.getChildCount();
+
+        int visibleNotifications = 0;
+        boolean onKeyguard = mState == StatusBarState.KEYGUARD;
+        int maxNotifications = -1;
+        if (onKeyguard) {
+            maxNotifications = getMaxKeyguardNotifications(true /* recompute */);
+        }
+        mStackScroller.setMaxDisplayedNotifications(maxNotifications);
+        Stack<ExpandableNotificationRow> stack = new Stack<>();
+        for (int i = N - 1; i >= 0; i--) {
+            View child = mStackScroller.getChildAt(i);
+            if (!(child instanceof ExpandableNotificationRow)) {
+                continue;
+            }
+            stack.push((ExpandableNotificationRow) child);
+        }
+        while(!stack.isEmpty()) {
+            ExpandableNotificationRow row = stack.pop();
+            NotificationData.Entry entry = row.getEntry();
+            boolean childNotification = mGroupManager.isChildInGroupWithSummary(entry.notification);
+            if (onKeyguard) {
+                row.setOnKeyguard(true);
+            } else {
+                row.setOnKeyguard(false);
+                row.setSystemExpanded(visibleNotifications == 0 && !childNotification);
+            }
+            entry.row.setShowAmbient(isDozing());
+            int userId = entry.notification.getUserId();
+            boolean suppressedSummary = mGroupManager.isSummaryOfSuppressedGroup(
+                    entry.notification) && !entry.row.isRemoved();
+            boolean showOnKeyguard = shouldShowOnKeyguard(entry.notification);
+            if (suppressedSummary
+                    || (isLockscreenPublicMode(userId) && !mShowLockscreenNotifications)
+                    || (onKeyguard && !showOnKeyguard)) {
+                entry.row.setVisibility(View.GONE);
+            } else {
+                boolean wasGone = entry.row.getVisibility() == View.GONE;
+                if (wasGone) {
+                    entry.row.setVisibility(View.VISIBLE);
+                }
+                if (!childNotification && !entry.row.isRemoved()) {
+                    if (wasGone) {
+                        // notify the scroller of a child addition
+                        mStackScroller.generateAddAnimation(entry.row,
+                                !showOnKeyguard /* fromMoreCard */);
+                    }
+                    visibleNotifications++;
+                }
+            }
+            if (row.isSummaryWithChildren()) {
+                List<ExpandableNotificationRow> notificationChildren =
+                        row.getNotificationChildren();
+                int size = notificationChildren.size();
+                for (int i = size - 1; i >= 0; i--) {
+                    stack.push(notificationChildren.get(i));
+                }
+            }
+        }
+
+        mStackScroller.changeViewPosition(mDismissView, mStackScroller.getChildCount() - 1);
+        mStackScroller.changeViewPosition(mEmptyShadeView, mStackScroller.getChildCount() - 2);
+        mStackScroller.changeViewPosition(mNotificationShelf, mStackScroller.getChildCount() - 3);
+    }
+
+    public boolean shouldShowOnKeyguard(StatusBarNotification sbn) {
+        return mShowLockscreenNotifications && !mNotificationData.isAmbient(sbn.getKey());
+    }
+
+    // extended in StatusBar
+    protected void setShowLockscreenNotifications(boolean show) {
+        mShowLockscreenNotifications = show;
+    }
+
+    protected void setLockScreenAllowRemoteInput(boolean allowLockscreenRemoteInput) {
+        mAllowLockscreenRemoteInput = allowLockscreenRemoteInput;
+    }
+
+    private void updateLockscreenNotificationSetting() {
+        final boolean show = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
+                1,
+                mCurrentUserId) != 0;
+        final int dpmFlags = mDevicePolicyManager.getKeyguardDisabledFeatures(
+                null /* admin */, mCurrentUserId);
+        final boolean allowedByDpm = (dpmFlags
+                & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) == 0;
+
+        setShowLockscreenNotifications(show && allowedByDpm);
+
+        if (ENABLE_LOCK_SCREEN_ALLOW_REMOTE_INPUT) {
+            final boolean remoteInput = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                    Settings.Secure.LOCK_SCREEN_ALLOW_REMOTE_INPUT,
+                    0,
+                    mCurrentUserId) != 0;
+            final boolean remoteInputDpm =
+                    (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_REMOTE_INPUT) == 0;
+
+            setLockScreenAllowRemoteInput(remoteInput && remoteInputDpm);
+        } else {
+            setLockScreenAllowRemoteInput(false);
+        }
+    }
+
+    public void updateNotification(StatusBarNotification notification, RankingMap ranking) {
+        if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
+
+        final String key = notification.getKey();
+        Entry entry = mNotificationData.get(key);
+        if (entry == null) {
+            return;
+        } else {
+            mHeadsUpEntriesToRemoveOnSwitch.remove(entry);
+            mRemoteInputEntriesToRemoveOnCollapse.remove(entry);
+        }
+
+        Notification n = notification.getNotification();
+        mNotificationData.updateRanking(ranking);
+
+        boolean applyInPlace;
+        try {
+            applyInPlace = entry.cacheContentViews(mContext, notification.getNotification(),
+                    mNotificationData.isAmbient(key));
+        } catch (RuntimeException e) {
+            Log.e(TAG, "Unable to get notification remote views", e);
+            applyInPlace = false;
+        }
+        boolean shouldPeek = shouldPeek(entry, notification);
+        boolean alertAgain = alertAgain(entry, n);
+        if (DEBUG) {
+            Log.d(TAG, "applyInPlace=" + applyInPlace
+                    + " shouldPeek=" + shouldPeek
+                    + " alertAgain=" + alertAgain);
+        }
+
+        final StatusBarNotification oldNotification = entry.notification;
+        entry.notification = notification;
+        mGroupManager.onEntryUpdated(entry, oldNotification);
+
+        boolean updateSuccessful = false;
+        try {
+            if (applyInPlace) {
+                if (DEBUG) Log.d(TAG, "reusing notification for key: " + key);
+                try {
+                    entry.updateIcons(mContext, n);
+                    updateNotificationViews(entry, notification);
+                    updateSuccessful = true;
+                } catch (RuntimeException e) {
+                    // It failed to apply cleanly.
+                    Log.w(TAG, "Couldn't reapply views for package " +
+                            notification.getPackageName(), e);
+                }
+            }
+            if (!updateSuccessful) {
+                entry.updateIcons(mContext, n);
+                if (!inflateViews(entry, mStackScroller)) {
+                    handleNotificationError(notification, "Couldn't update remote views for: "
+                            + notification);
+                }
+            }
+        } catch (NotificationData.IconException e) {
+            handleNotificationError(notification, e.getMessage());
+        }
+        updateHeadsUp(key, entry, shouldPeek, alertAgain);
+        updateNotifications();
+
+        if (!notification.isClearable()) {
+            // The user may have performed a dismiss action on the notification, since it's
+            // not clearable we should snap it back.
+            mStackScroller.snapViewIfNeeded(entry.row);
+        }
+
+        if (DEBUG) {
+            // Is this for you?
+            boolean isForCurrentUser = isNotificationForCurrentProfiles(notification);
+            Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
+        }
+
+        setAreThereNotifications();
+    }
+
+    private void updateNotificationViews(Entry entry, StatusBarNotification sbn) {
+        final RemoteViews contentView = entry.cachedContentView;
+        final RemoteViews bigContentView = entry.cachedBigContentView;
+        final RemoteViews headsUpContentView = entry.cachedHeadsUpContentView;
+        final RemoteViews publicContentView = entry.cachedPublicContentView;
+
+        // Reapply the RemoteViews
+        contentView.reapply(mContext, entry.getContentView(), mOnClickHandler);
+        if (bigContentView != null && entry.getExpandedContentView() != null) {
+            bigContentView.reapply(sbn.getPackageContext(mContext),
+                    entry.getExpandedContentView(),
+                    mOnClickHandler);
+        }
+        View headsUpChild = entry.getHeadsUpContentView();
+        if (headsUpContentView != null && headsUpChild != null) {
+            headsUpContentView.reapply(sbn.getPackageContext(mContext),
+                    headsUpChild, mOnClickHandler);
+        }
+        if (publicContentView != null && entry.getPublicContentView() != null) {
+            publicContentView.reapply(sbn.getPackageContext(mContext),
+                    entry.getPublicContentView(), mOnClickHandler);
+        }
+        // update the contentIntent
+        mNotificationClicker.register(entry.row, sbn);
+
+        entry.row.onNotificationUpdated(entry);
+        entry.row.resetHeight();
+    }
+
+    protected void updatePublicContentView(Entry entry,
+            StatusBarNotification sbn) {
+        final RemoteViews publicContentView = entry.cachedPublicContentView;
+        View inflatedView = entry.getPublicContentView();
+        if (entry.autoRedacted && publicContentView != null && inflatedView != null) {
+            final boolean disabledByPolicy =
+                    !adminAllowsUnredactedNotifications(entry.notification.getUserId());
+            String notificationHiddenText = mContext.getString(disabledByPolicy
+                    ? com.android.internal.R.string.notification_hidden_by_policy_text
+                    : com.android.internal.R.string.notification_hidden_text);
+            TextView titleView = (TextView) inflatedView.findViewById(android.R.id.title);
+            if (titleView != null
+                    && !titleView.getText().toString().equals(notificationHiddenText)) {
+                publicContentView.setTextViewText(android.R.id.title, notificationHiddenText);
+                publicContentView.reapply(sbn.getPackageContext(mContext),
+                        inflatedView, mOnClickHandler);
+                entry.row.onNotificationUpdated(entry);
+            }
+        }
+    }
+
+    protected void notifyHeadsUpScreenOff() {
+        maybeEscalateHeadsUp();
+    }
+
+    private boolean alertAgain(Entry oldEntry, Notification newNotification) {
+        return oldEntry == null || !oldEntry.hasInterrupted()
+                || (newNotification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0;
+    }
+
+    protected boolean shouldPeek(Entry entry) {
+        return shouldPeek(entry, entry.notification);
+    }
+
+    protected boolean shouldPeek(Entry entry, StatusBarNotification sbn) {
+        if (!mUseHeadsUp || isDeviceInVrMode()) {
+            return false;
+        }
+
+        if (mNotificationData.shouldFilterOut(sbn)) {
+            if (DEBUG) Log.d(TAG, "No peeking: filtered notification: " + sbn.getKey());
+            return false;
+        }
+
+        boolean inUse = mPowerManager.isScreenOn();
+        try {
+            inUse = inUse && !mDreamManager.isDreaming();
+        } catch (RemoteException e) {
+            Log.d(TAG, "failed to query dream manager", e);
+        }
+
+        if (!inUse && !isDozing()) {
+            if (DEBUG) {
+                Log.d(TAG, "No peeking: not in use: " + sbn.getKey());
+            }
+            return false;
+        }
+
+        if (mNotificationData.shouldSuppressScreenOn(sbn.getKey())) {
+            if (DEBUG) Log.d(TAG, "No peeking: suppressed by DND: " + sbn.getKey());
+            return false;
+        }
+
+        if (entry.hasJustLaunchedFullScreenIntent()) {
+            if (DEBUG) Log.d(TAG, "No peeking: recent fullscreen: " + sbn.getKey());
+            return false;
+        }
+
+        if (isSnoozedPackage(sbn)) {
+            if (DEBUG) Log.d(TAG, "No peeking: snoozed package: " + sbn.getKey());
+            return false;
+        }
+
+        if (mNotificationData.getImportance(sbn.getKey()) < NotificationManager.IMPORTANCE_HIGH) {
+            if (DEBUG) Log.d(TAG, "No peeking: unimportant notification: " + sbn.getKey());
+            return false;
+        }
+
+        if (sbn.getNotification().fullScreenIntent != null) {
+            if (mAccessibilityManager.isTouchExplorationEnabled()) {
+                if (DEBUG) Log.d(TAG, "No peeking: accessible fullscreen: " + sbn.getKey());
+                return false;
+            } else {
+                // we only allow head-up on the lockscreen if it doesn't have a fullscreen intent
+                return !mStatusBarKeyguardViewManager.isShowing()
+                        || mStatusBarKeyguardViewManager.isOccluded();
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * @return Whether the security bouncer from Keyguard is showing.
+     */
+    public boolean isBouncerShowing() {
+        return mBouncerShowing;
+    }
+
+    /**
+     * @return a PackageManger for userId or if userId is < 0 (USER_ALL etc) then
+     *         return PackageManager for mContext
+     */
+    public static PackageManager getPackageManagerForUser(Context context, int userId) {
+        Context contextForUser = context;
+        // UserHandle defines special userId as negative values, e.g. USER_ALL
+        if (userId >= 0) {
+            try {
+                // Create a context for the correct user so if a package isn't installed
+                // for user 0 we can still load information about the package.
+                contextForUser =
+                        context.createPackageContextAsUser(context.getPackageName(),
+                        Context.CONTEXT_RESTRICTED,
+                        new UserHandle(userId));
+            } catch (NameNotFoundException e) {
+                // Shouldn't fail to find the package name for system ui.
+            }
+        }
+        return contextForUser.getPackageManager();
+    }
+
+    @Override
+    public void logNotificationExpansion(String key, boolean userAction, boolean expanded) {
+        try {
+            mBarService.onNotificationExpansionChanged(key, userAction, expanded);
+        } catch (RemoteException e) {
+            // Ignore.
+        }
+    }
+
+    public boolean isKeyguardSecure() {
+        if (mStatusBarKeyguardViewManager == null) {
+            // startKeyguard() hasn't been called yet, so we don't know.
+            // Make sure anything that needs to know isKeyguardSecure() checks and re-checks this
+            // value onVisibilityChanged().
+            Slog.w(TAG, "isKeyguardSecure() called before startKeyguard(), returning false",
+                    new Throwable());
+            return false;
+        }
+        return mStatusBarKeyguardViewManager.isSecure();
+    }
+
+    @Override
+    public void showAssistDisclosure() {
+        if (mAssistManager != null) {
+            mAssistManager.showDisclosure();
+        }
+    }
+
+    @Override
+    public void startAssist(Bundle args) {
+        if (mAssistManager != null) {
+            mAssistManager.startAssist(args);
+        }
+    }
+    // End Extra BaseStatusBarMethods.
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index a0425e6..46ca3c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.phone;
 
 import android.animation.ArgbEvaluator;
-import android.animation.ValueAnimator;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -25,8 +24,6 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Icon;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.SystemClock;
 import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.ArraySet;
@@ -64,7 +61,7 @@
     public static final int DEFAULT_ICON_TINT = Color.WHITE;
 
     private Context mContext;
-    private PhoneStatusBar mPhoneStatusBar;
+    private StatusBar mStatusBar;
     private DemoStatusIcons mDemoStatusIcons;
 
     private LinearLayout mSystemIconArea;
@@ -100,11 +97,11 @@
     private final ArraySet<String> mIconBlacklist = new ArraySet<>();
 
     public StatusBarIconController(Context context, View statusBar, View keyguardStatusBar,
-            PhoneStatusBar phoneStatusBar) {
+            StatusBar phoneStatusBar) {
         super(context.getResources().getStringArray(
                 com.android.internal.R.array.config_statusBarIcons));
         mContext = context;
-        mPhoneStatusBar = phoneStatusBar;
+        mStatusBar = phoneStatusBar;
         mSystemIconArea = (LinearLayout) statusBar.findViewById(R.id.system_icon_area);
         mStatusIcons = (LinearLayout) statusBar.findViewById(R.id.statusIcons);
         mSignalCluster = (SignalClusterView) statusBar.findViewById(R.id.signal_cluster);
@@ -405,11 +402,11 @@
                 .withEndAction(null);
 
         // Synchronize the motion with the Keyguard fading if necessary.
-        if (mPhoneStatusBar.isKeyguardFadingAway()) {
+        if (mStatusBar.isKeyguardFadingAway()) {
             v.animate()
-                    .setDuration(mPhoneStatusBar.getKeyguardFadingAwayDuration())
+                    .setDuration(mStatusBar.getKeyguardFadingAwayDuration())
                     .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
-                    .setStartDelay(mPhoneStatusBar.getKeyguardFadingAwayDelay())
+                    .setStartDelay(mStatusBar.getKeyguardFadingAwayDelay())
                     .start();
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 7e5a7da..8d5d890 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -70,7 +70,7 @@
 
     protected LockPatternUtils mLockPatternUtils;
     protected ViewMediatorCallback mViewMediatorCallback;
-    protected PhoneStatusBar mPhoneStatusBar;
+    protected StatusBar mStatusBar;
     private ScrimController mScrimController;
     private FingerprintUnlockController mFingerprintUnlockController;
 
@@ -103,12 +103,12 @@
         mLockPatternUtils = lockPatternUtils;
     }
 
-    public void registerStatusBar(PhoneStatusBar phoneStatusBar,
+    public void registerStatusBar(StatusBar statusBar,
             ViewGroup container, StatusBarWindowManager statusBarWindowManager,
             ScrimController scrimController,
             FingerprintUnlockController fingerprintUnlockController,
             DismissCallbackRegistry dismissCallbackRegistry) {
-        mPhoneStatusBar = phoneStatusBar;
+        mStatusBar = statusBar;
         mContainer = container;
         mStatusBarWindowManager = statusBarWindowManager;
         mScrimController = scrimController;
@@ -136,10 +136,10 @@
         if (mBouncer.needsFullscreenBouncer()) {
 
             // The keyguard might be showing (already). So we need to hide it.
-            mPhoneStatusBar.hideKeyguard();
+            mStatusBar.hideKeyguard();
             mBouncer.show(true /* resetSecuritySelection */);
         } else {
-            mPhoneStatusBar.showKeyguard();
+            mStatusBar.showKeyguard();
             if (hideBouncerWhenShowing) {
                 mBouncer.hide(false /* destroyView */);
                 mBouncer.prepare();
@@ -180,8 +180,8 @@
     public void reset(boolean hideBouncerWhenShowing) {
         if (mShowing) {
             if (mOccluded) {
-                mPhoneStatusBar.hideKeyguard();
-                mPhoneStatusBar.stopWaitingForKeyguardExit();
+                mStatusBar.hideKeyguard();
+                mStatusBar.stopWaitingForKeyguardExit();
                 mBouncer.hide(false /* destroyView */);
             } else {
                 showBouncerOrKeyguard(hideBouncerWhenShowing);
@@ -192,12 +192,12 @@
     }
 
     public void onStartedGoingToSleep() {
-        mPhoneStatusBar.onStartedGoingToSleep();
+        mStatusBar.onStartedGoingToSleep();
     }
 
     public void onFinishedGoingToSleep() {
         mDeviceInteractive = false;
-        mPhoneStatusBar.onFinishedGoingToSleep();
+        mStatusBar.onFinishedGoingToSleep();
         mBouncer.onScreenTurnedOff();
     }
 
@@ -205,13 +205,13 @@
         Trace.beginSection("StatusBarKeyguardViewManager#onStartedWakingUp");
         mDeviceInteractive = true;
         mDeviceWillWakeUp = false;
-        mPhoneStatusBar.onStartedWakingUp();
+        mStatusBar.onStartedWakingUp();
         Trace.endSection();
     }
 
     public void onScreenTurningOn() {
         Trace.beginSection("StatusBarKeyguardViewManager#onScreenTurningOn");
-        mPhoneStatusBar.onScreenTurningOn();
+        mStatusBar.onScreenTurningOn();
         Trace.endSection();
     }
 
@@ -228,7 +228,7 @@
                     true /* skipFirstFrame */);
             updateStates();
         }
-        mPhoneStatusBar.onScreenTurnedOn();
+        mStatusBar.onScreenTurnedOn();
         Trace.endSection();
     }
 
@@ -240,7 +240,7 @@
 
     public void onScreenTurnedOff() {
         mScreenTurnedOn = false;
-        mPhoneStatusBar.onScreenTurnedOff();
+        mStatusBar.onScreenTurnedOff();
     }
 
     public void notifyDeviceWakeUpRequested() {
@@ -257,12 +257,12 @@
 
     public void setOccluded(boolean occluded, boolean animate) {
         if (occluded != mOccluded) {
-            mPhoneStatusBar.onKeyguardOccludedChanged(occluded);
+            mStatusBar.onKeyguardOccludedChanged(occluded);
         }
         if (occluded && !mOccluded && mShowing) {
-            if (mPhoneStatusBar.isInLaunchTransition()) {
+            if (mStatusBar.isInLaunchTransition()) {
                 mOccluded = true;
-                mPhoneStatusBar.fadeKeyguardAfterLaunchTransition(null /* beforeFading */,
+                mStatusBar.fadeKeyguardAfterLaunchTransition(null /* beforeFading */,
                         new Runnable() {
                             @Override
                             public void run() {
@@ -275,7 +275,7 @@
         }
         mOccluded = occluded;
         if (mShowing) {
-            mPhoneStatusBar.updateMediaMetaData(false, animate && !occluded);
+            mStatusBar.updateMediaMetaData(false, animate && !occluded);
         }
         mStatusBarWindowManager.setKeyguardOccluded(occluded);
 
@@ -283,7 +283,7 @@
         // a FLAG_DISMISS_KEYGUARD_ACTIVITY.
         reset(false /* hideBouncerWhenShowing*/);
         if (animate && !occluded && mShowing) {
-            mPhoneStatusBar.animateKeyguardUnoccluding();
+            mStatusBar.animateKeyguardUnoccluding();
         }
     }
 
@@ -318,8 +318,8 @@
         long uptimeMillis = SystemClock.uptimeMillis();
         long delay = Math.max(0, startTime + HIDE_TIMING_CORRECTION_MS - uptimeMillis);
 
-        if (mPhoneStatusBar.isInLaunchTransition() ) {
-            mPhoneStatusBar.fadeKeyguardAfterLaunchTransition(new Runnable() {
+        if (mStatusBar.isInLaunchTransition() ) {
+            mStatusBar.fadeKeyguardAfterLaunchTransition(new Runnable() {
                 @Override
                 public void run() {
                     mStatusBarWindowManager.setKeyguardShowing(false);
@@ -327,14 +327,14 @@
                     mBouncer.hide(true /* destroyView */);
                     updateStates();
                     mScrimController.animateKeyguardFadingOut(
-                            PhoneStatusBar.FADE_KEYGUARD_START_DELAY,
-                            PhoneStatusBar.FADE_KEYGUARD_DURATION, null,
+                            StatusBar.FADE_KEYGUARD_START_DELAY,
+                            StatusBar.FADE_KEYGUARD_DURATION, null,
                             false /* skipFirstFrame */);
                 }
             }, new Runnable() {
                 @Override
                 public void run() {
-                    mPhoneStatusBar.hideKeyguard();
+                    mStatusBar.hideKeyguard();
                     mStatusBarWindowManager.setKeyguardFadingAway(false);
                     mViewMediatorCallback.keyguardGone();
                     executeAfterKeyguardGoneAction();
@@ -348,19 +348,19 @@
                 delay = 0;
                 fadeoutDuration = 240;
             }
-            mPhoneStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration);
+            mStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration);
             mFingerprintUnlockController.startKeyguardFadingAway();
             mBouncer.hide(true /* destroyView */);
             updateStates();
             if (wakeUnlockPulsing) {
                 mStatusBarWindowManager.setKeyguardFadingAway(true);
-                mPhoneStatusBar.fadeKeyguardWhilePulsing();
+                mStatusBar.fadeKeyguardWhilePulsing();
                 animateScrimControllerKeyguardFadingOut(delay, fadeoutDuration,
-                        mPhoneStatusBar::hideKeyguard, false /* skipFirstFrame */);
+                        mStatusBar::hideKeyguard, false /* skipFirstFrame */);
             } else {
                 mFingerprintUnlockController.startKeyguardFadingAway();
-                mPhoneStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration);
-                boolean staying = mPhoneStatusBar.hideKeyguard();
+                mStatusBar.setKeyguardFadingAway(startTime, delay, fadeoutDuration);
+                boolean staying = mStatusBar.hideKeyguard();
                 if (!staying) {
                     mStatusBarWindowManager.setKeyguardFadingAway(true);
                     if (mFingerprintUnlockController.getMode() == MODE_WAKE_AND_UNLOCK) {
@@ -379,7 +379,7 @@
                     }
                 } else {
                     mScrimController.animateGoingToFullShade(delay, fadeoutDuration);
-                    mPhoneStatusBar.finishKeyguardFadingAway();
+                    mStatusBar.finishKeyguardFadingAway();
                 }
             }
             mStatusBarWindowManager.setKeyguardShowing(false);
@@ -408,7 +408,7 @@
                 }
                 mContainer.postDelayed(() -> mStatusBarWindowManager.setKeyguardFadingAway(false),
                         100);
-                mPhoneStatusBar.finishKeyguardFadingAway();
+                mStatusBar.finishKeyguardFadingAway();
                 mFingerprintUnlockController.finishKeyguardFadingAway();
                 WindowManagerGlobal.getInstance().trimMemory(
                         ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
@@ -438,7 +438,7 @@
      * Dismisses the keyguard by going to the next screen or making it gone.
      */
     public void dismissAndCollapse() {
-        mPhoneStatusBar.executeRunnableDismissingKeyguard(null, null, true, false, true);
+        mStatusBar.executeRunnableDismissingKeyguard(null, null, true, false, true);
     }
 
     public void dismiss() {
@@ -466,7 +466,7 @@
      */
     public boolean onBackPressed() {
         if (mBouncer.isShowing()) {
-            mPhoneStatusBar.endAffordanceLaunch();
+            mStatusBar.endAffordanceLaunch();
             reset(true /* hideBouncerWhenShowing */);
             return true;
         }
@@ -478,8 +478,8 @@
     }
 
     private long getNavBarShowDelay() {
-        if (mPhoneStatusBar.isKeyguardFadingAway()) {
-            return mPhoneStatusBar.getKeyguardFadingAwayDelay();
+        if (mStatusBar.isKeyguardFadingAway()) {
+            return mStatusBar.getKeyguardFadingAwayDelay();
         } else {
 
             // Keyguard is not going away, thus we are showing the navigation bar because the
@@ -491,7 +491,7 @@
     private Runnable mMakeNavigationBarVisibleRunnable = new Runnable() {
         @Override
         public void run() {
-            mPhoneStatusBar.getNavigationBarView().getRootView().setVisibility(View.VISIBLE);
+            mStatusBar.getNavigationBarView().getRootView().setVisibility(View.VISIBLE);
         }
     };
 
@@ -516,7 +516,7 @@
         boolean navBarVisible = isNavBarVisible();
         boolean lastNavBarVisible = getLastNavBarVisible();
         if (navBarVisible != lastNavBarVisible || mFirstUpdate) {
-            if (mPhoneStatusBar.getNavigationBarView() != null) {
+            if (mStatusBar.getNavigationBarView() != null) {
                 if (navBarVisible) {
                     long delay = getNavBarShowDelay();
                     if (delay == 0) {
@@ -527,14 +527,14 @@
                     }
                 } else {
                     mContainer.removeCallbacks(mMakeNavigationBarVisibleRunnable);
-                    mPhoneStatusBar.getNavigationBarView().getRootView().setVisibility(View.GONE);
+                    mStatusBar.getNavigationBarView().getRootView().setVisibility(View.GONE);
                 }
             }
         }
 
         if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
             mStatusBarWindowManager.setBouncerShowing(bouncerShowing);
-            mPhoneStatusBar.setBouncerShowing(bouncerShowing);
+            mStatusBar.setBouncerShowing(bouncerShowing);
             mScrimController.setBouncerShowing(bouncerShowing);
         }
 
@@ -553,7 +553,7 @@
         mLastBouncerDismissible = bouncerDismissible;
         mLastRemoteInputActive = remoteInputActive;
 
-        mPhoneStatusBar.onKeyguardViewManagerStatesUpdated();
+        mStatusBar.onKeyguardViewManagerStatesUpdated();
     }
 
     /**
@@ -583,11 +583,11 @@
     }
 
     public boolean shouldDisableWindowAnimationsForUnlock() {
-        return mPhoneStatusBar.isInLaunchTransition();
+        return mStatusBar.isInLaunchTransition();
     }
 
     public boolean isGoingToNotificationShade() {
-        return mPhoneStatusBar.isGoingToNotificationShade();
+        return mStatusBar.isGoingToNotificationShade();
     }
 
     public boolean isSecure(int userId) {
@@ -595,11 +595,11 @@
     }
 
     public void keyguardGoingAway() {
-        mPhoneStatusBar.keyguardGoingAway();
+        mStatusBar.keyguardGoingAway();
     }
 
     public void animateCollapsePanels(float speedUpFactor) {
-        mPhoneStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */,
+        mStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */,
                 false /* delayed */, speedUpFactor);
     }
 
@@ -616,6 +616,6 @@
     }
 
     public ViewRootImpl getViewRootImpl() {
-        return mPhoneStatusBar.getStatusBarView().getViewRootImpl();
+        return mStatusBar.getStatusBarView().getViewRootImpl();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index 0660054..16999b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -25,7 +25,6 @@
 import android.os.Binder;
 import android.os.RemoteException;
 import android.os.SystemProperties;
-import android.os.Trace;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.View;
@@ -34,7 +33,6 @@
 
 import com.android.keyguard.R;
 import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.StatusBarState;
 
@@ -140,7 +138,7 @@
     private void applyFocusableFlag(State state) {
         boolean panelFocusable = state.statusBarFocusable && state.panelExpanded;
         if (state.bouncerShowing && (state.keyguardOccluded || state.keyguardNeedsInput)
-                || BaseStatusBar.ENABLE_REMOTE_INPUT && state.remoteInputActive) {
+                || StatusBar.ENABLE_REMOTE_INPUT && state.remoteInputActive) {
             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
         } else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) {
@@ -385,7 +383,7 @@
         boolean backdropShowing;
 
         /**
-         * The {@link BaseStatusBar} state from the status bar.
+         * The {@link StatusBar} state from the status bar.
          */
         int statusBarState;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index ccd6357..7c42d00 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -34,7 +34,6 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
-import android.os.Trace;
 import android.util.AttributeSet;
 import android.view.ActionMode;
 import android.view.InputQueue;
@@ -56,7 +55,6 @@
 import com.android.internal.widget.FloatingToolbar;
 import com.android.systemui.R;
 import com.android.systemui.classifier.FalsingManager;
-import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.DragDownHelper;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
@@ -64,7 +62,7 @@
 
 public class StatusBarWindowView extends FrameLayout {
     public static final String TAG = "StatusBarWindowView";
-    public static final boolean DEBUG = BaseStatusBar.DEBUG;
+    public static final boolean DEBUG = StatusBar.DEBUG;
 
     private DragDownHelper mDragDownHelper;
     private NotificationStackScrollLayout mStackScrollLayout;
@@ -74,7 +72,7 @@
     private int mRightInset = 0;
     private int mLeftInset = 0;
 
-    private PhoneStatusBar mService;
+    private StatusBar mService;
     private final Paint mTransparentSrcPaint = new Paint();
     private FalsingManager mFalsingManager;
 
@@ -173,7 +171,7 @@
         }
     }
 
-    public void setService(PhoneStatusBar service) {
+    public void setService(StatusBar service) {
         mService = service;
         mDragDownHelper = new DragDownHelper(getContext(), this, mStackScrollLayout, mService);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
index e7056a6..5ab99e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
@@ -125,14 +125,14 @@
     public void setMobileDataIndicators(final IconState statusIcon, final IconState qsIcon,
             final int statusType, final int qsType,final boolean activityIn,
             final boolean activityOut, final String typeContentDescription,
-            final String description, final boolean isWide, final int subId) {
+            final String description, final boolean isWide, final int subId, boolean roaming) {
         post(new Runnable() {
             @Override
             public void run() {
                 for (SignalCallback signalCluster : mSignalCallbacks) {
                     signalCluster.setMobileDataIndicators(statusIcon, qsIcon, statusType, qsType,
                             activityIn, activityOut, typeContentDescription, description, isWide,
-                            subId);
+                            subId, roaming);
                 }
             }
         });
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index a8d8f60..8c805fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -37,7 +37,7 @@
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.notification.VisualStabilityManager;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.StatusBar;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -90,7 +90,7 @@
     private final int mStatusBarHeight;
     private final Context mContext;
     private final NotificationGroupManager mGroupManager;
-    private PhoneStatusBar mBar;
+    private StatusBar mBar;
     private int mSnoozeLengthMs;
     private ContentObserver mSettingsObserver;
     private HashMap<String, HeadsUpEntry> mHeadsUpEntries = new HashMap<>();
@@ -162,7 +162,7 @@
         mIsObserving = shouldObserve;
     }
 
-    public void setBar(PhoneStatusBar bar) {
+    public void setBar(StatusBar bar) {
         mBar = bar;
     }
 
@@ -170,7 +170,7 @@
         mListeners.add(listener);
     }
 
-    public PhoneStatusBar getBar() {
+    public StatusBar getBar() {
         return mBar;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 45cfbdc..882902e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -116,18 +116,18 @@
         mOnClickListener = onClickListener;
     }
 
-    public void loadAsync(String uri) {
-        new AsyncTask<String, Void, Drawable>() {
+    public void loadAsync(Icon icon) {
+        new AsyncTask<Icon, Void, Drawable>() {
             @Override
-            protected Drawable doInBackground(String... params) {
-                return Icon.createWithContentUri(params[0]).loadDrawable(mContext);
+            protected Drawable doInBackground(Icon... params) {
+                return params[0].loadDrawable(mContext);
             }
 
             @Override
             protected void onPostExecute(Drawable drawable) {
                 setImageDrawable(drawable);
             }
-        }.execute(uri);
+        }.execute(icon);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 83463e2..03c46e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -226,10 +226,8 @@
         final boolean dataDisabled = mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED
                 && mCurrentState.userSetup;
 
-        // Show icon in QS when we are connected or need to show roaming or data is disabled.
-        boolean showDataIcon = mCurrentState.dataConnected
-                || mCurrentState.iconGroup == TelephonyIcons.ROAMING
-                || dataDisabled;
+        // Show icon in QS when we are connected or data is disabled.
+        boolean showDataIcon = mCurrentState.dataConnected || dataDisabled;
         IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode,
                 getCurrentIconId(), contentDescription);
 
@@ -249,13 +247,11 @@
         boolean activityOut = mCurrentState.dataConnected
                         && !mCurrentState.carrierNetworkChangeMode
                         && mCurrentState.activityOut;
-        showDataIcon &= mCurrentState.isDefault
-                || mCurrentState.iconGroup == TelephonyIcons.ROAMING
-                || dataDisabled;
+        showDataIcon &= mCurrentState.isDefault || dataDisabled;
         int typeIcon = showDataIcon ? icons.mDataType : 0;
         callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
                 activityIn, activityOut, dataContentDescription, description, icons.mIsWide,
-                mSubscriptionInfo.getSubscriptionId());
+                mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming);
     }
 
     @Override
@@ -405,10 +401,9 @@
         mCurrentState.dataConnected = mCurrentState.connected
                 && mDataState == TelephonyManager.DATA_CONNECTED;
 
+        mCurrentState.roaming = isRoaming();
         if (isCarrierNetworkChangeActive()) {
             mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
-        } else if (isRoaming()) {
-            mCurrentState.iconGroup = TelephonyIcons.ROAMING;
         } else if (isDataDisabled()) {
             mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED;
         }
@@ -541,6 +536,7 @@
         boolean carrierNetworkChangeMode;
         boolean isDefault;
         boolean userSetup;
+        boolean roaming;
 
         @Override
         public void copyFrom(State s) {
@@ -555,6 +551,7 @@
             airplaneMode = state.airplaneMode;
             carrierNetworkChangeMode = state.carrierNetworkChangeMode;
             userSetup = state.userSetup;
+            roaming = state.roaming;
         }
 
         @Override
@@ -565,6 +562,7 @@
             builder.append("networkName=").append(networkName).append(',');
             builder.append("networkNameData=").append(networkNameData).append(',');
             builder.append("dataConnected=").append(dataConnected).append(',');
+            builder.append("roaming=").append(roaming).append(',');
             builder.append("isDefault=").append(isDefault).append(',');
             builder.append("isEmergency=").append(isEmergency).append(',');
             builder.append("airplaneMode=").append(airplaneMode).append(',');
@@ -584,7 +582,8 @@
                     && ((MobileState) o).airplaneMode == airplaneMode
                     && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode
                     && ((MobileState) o).userSetup == userSetup
-                    && ((MobileState) o).isDefault == isDefault;
+                    && ((MobileState) o).isDefault == isDefault
+                    && ((MobileState) o).roaming == roaming;
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index a3a9d71..eb47a3c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -53,7 +53,7 @@
 
         default void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
                 int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
-                String description, boolean isWide, int subId) {}
+                String description, boolean isWide, int subId, boolean roaming) {}
         default void setSubs(List<SubscriptionInfo> subs) {}
         default void setNoSims(boolean show) {}
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 5e13f59..d7c919d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -822,10 +822,12 @@
                             datatype.equals("h") ? TelephonyIcons.H :
                             datatype.equals("lte") ? TelephonyIcons.LTE :
                             datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS :
-                            datatype.equals("roam") ? TelephonyIcons.ROAMING :
                             datatype.equals("dis") ? TelephonyIcons.DATA_DISABLED :
                             TelephonyIcons.UNKNOWN;
                 }
+                if (args.containsKey("roam")) {
+                    controller.getState().roaming = "show".equals(args.getString("roam"));
+                }
                 int[][] icons = TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH;
                 String level = args.getString("level");
                 if (level != null) {
@@ -833,6 +835,10 @@
                             : Math.min(Integer.parseInt(level), icons[0].length - 1);
                     controller.getState().connected = controller.getState().level >= 0;
                 }
+                String activity = args.getString("activity");
+                if (activity != null) {
+                    controller.setActivity(Integer.parseInt(activity));
+                }
                 controller.getState().enabled = show;
                 controller.notifyListeners();
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 44ec283..784f25e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -56,6 +56,7 @@
 import com.android.systemui.statusbar.ExpandableView;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.notification.NotificationViewWrapper;
 import com.android.systemui.statusbar.stack.ScrollContainer;
 import com.android.systemui.statusbar.stack.StackStateAnimator;
 
@@ -90,6 +91,7 @@
     private int mRevealR;
 
     private boolean mResetting;
+    private NotificationViewWrapper mWrapper;
 
     public RemoteInputView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -210,11 +212,17 @@
                     @Override
                     public void onAnimationEnd(Animator animation) {
                         setVisibility(INVISIBLE);
+                        if (mWrapper != null) {
+                            mWrapper.setRemoteInputVisible(false);
+                        }
                     }
                 });
                 reveal.start();
             } else {
                 setVisibility(INVISIBLE);
+                if (mWrapper != null) {
+                    mWrapper.setRemoteInputVisible(false);
+                }
             }
         }
         MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_REMOTE_INPUT_CLOSE,
@@ -267,6 +275,9 @@
                 mEntry.notification.getPackageName());
 
         setVisibility(VISIBLE);
+        if (mWrapper != null) {
+            mWrapper.setRemoteInputVisible(true);
+        }
         mController.addRemoteInput(mEntry, mToken);
         mEditText.setInnerFocusable(true);
         mEditText.mShowImeOnInputConnection = true;
@@ -283,6 +294,10 @@
             // Update came in after we sent the reply, time to reset.
             reset();
         }
+
+        if (isActive() && mWrapper != null) {
+            mWrapper.setRemoteInputVisible(true);
+        }
     }
 
     private void reset() {
@@ -452,6 +467,10 @@
         super.dispatchFinishTemporaryDetach();
     }
 
+    public void setWrapper(NotificationViewWrapper wrapper) {
+        mWrapper = wrapper;
+    }
+
     /**
      * An EditText that changes appearance based on whether it's focusable and becomes
      * un-focusable whenever the user navigates away from it or it becomes invisible.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalCallbackAdapter.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalCallbackAdapter.java
deleted file mode 100644
index dce889f..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalCallbackAdapter.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.statusbar.policy;
-
-import android.telephony.SubscriptionInfo;
-
-import com.android.systemui.statusbar.policy.NetworkController.IconState;
-import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
-
-import java.util.List;
-
-
-/**
- * Provides empty implementations of SignalCallback for those that only want some of
- * the callbacks.
- */
-public class SignalCallbackAdapter implements SignalCallback {
-
-    @Override
-    public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
-            boolean activityIn, boolean activityOut, String description) {
-    }
-
-    @Override
-    public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
-            int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
-            String description, boolean isWide, int subId) {
-    }
-
-    @Override
-    public void setSubs(List<SubscriptionInfo> subs) {
-    }
-
-    @Override
-    public void setNoSims(boolean show) {
-    }
-
-    @Override
-    public void setEthernetIndicators(IconState icon) {
-    }
-
-    @Override
-    public void setIsAirplaneMode(IconState icon) {
-    }
-
-    @Override
-    public void setMobileDataEnabled(boolean enabled) {
-    }
-
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index ed8c7ff..6b2361e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -95,8 +95,6 @@
           R.drawable.ic_qs_signal_carrier_network_change_animation }
     };
 
-    static final int QS_DATA_R = R.drawable.ic_qs_signal_r;
-
     //***** Data connection icons
 
     //GSM/UMTS
@@ -211,7 +209,7 @@
     static final int QS_DATA_LTE_PLUS = R.drawable.ic_qs_signal_lte_plus;
 
     static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode;
-    static final int ROAMING_ICON = R.drawable.stat_sys_data_fully_connected_roam;
+    static final int ROAMING_ICON = R.drawable.stat_sys_roaming;
     static final int ICON_LTE = R.drawable.stat_sys_data_fully_connected_lte;
     static final int ICON_LTE_PLUS = R.drawable.stat_sys_data_fully_connected_lte_plus;
     static final int ICON_G = R.drawable.stat_sys_data_fully_connected_g;
@@ -410,21 +408,6 @@
             TelephonyIcons.QS_DATA_LTE_PLUS
             );
 
-    static final MobileIconGroup ROAMING = new MobileIconGroup(
-            "Roaming",
-            TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING,
-            TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
-            0, 0,
-            TelephonyIcons.TELEPHONY_NO_NETWORK,
-            TelephonyIcons.QS_TELEPHONY_NO_NETWORK,
-            AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
-            R.string.accessibility_data_connection_roaming,
-            TelephonyIcons.ROAMING_ICON,
-            false,
-            TelephonyIcons.QS_DATA_R
-            );
-
     static final MobileIconGroup DATA_DISABLED = new MobileIconGroup(
             "DataDisabled",
             TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index f71c5d1..fd71f43 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -61,6 +61,7 @@
 import com.android.systemui.qs.tiles.UserDetailView;
 import com.android.systemui.ActivityStarter;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.util.NotificationChannels;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -561,7 +562,7 @@
                     0, new Intent(ACTION_LOGOUT_USER), 0, UserHandle.SYSTEM);
             Notification.Builder builder = new Notification.Builder(mContext)
                     .setVisibility(Notification.VISIBILITY_SECRET)
-                    .setPriority(Notification.PRIORITY_MIN)
+                    .setChannel(NotificationChannels.USER)
                     .setSmallIcon(R.drawable.ic_person)
                     .setContentTitle(mContext.getString(R.string.user_logout_notification_title))
                     .setContentText(mContext.getString(R.string.user_logout_notification_text))
@@ -585,7 +586,7 @@
 
         Notification.Builder builder = new Notification.Builder(mContext)
                 .setVisibility(Notification.VISIBILITY_SECRET)
-                .setPriority(Notification.PRIORITY_MIN)
+                .setChannel(NotificationChannels.USER)
                 .setSmallIcon(R.drawable.ic_person)
                 .setContentTitle(mContext.getString(R.string.guest_notification_title))
                 .setContentText(mContext.getString(R.string.guest_notification_text))
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index 42c20ff..886b8be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -56,7 +56,7 @@
     private final WifiNetworkScoreCache mScoreCache;
     private final WifiStatusTracker mWifiTracker;
 
-    private boolean mScoringEnabled = false;
+    private boolean mScoringUiEnabled = false;
 
     public WifiSignalController(Context context, boolean hasMobileData,
             CallbackHandler callbackHandler, NetworkControllerImpl networkController,
@@ -95,25 +95,26 @@
 
         // Setup scoring
         mNetworkScoreManager = networkScoreManager;
+        configureScoringGating();
+        registerScoreCache();
+    }
+
+    private void configureScoringGating() {
         ContentObserver observer = new ContentObserver(new Handler(Looper.getMainLooper())) {
             @Override
             public void onChange(boolean selfChange) {
-                mScoringEnabled =
+                mScoringUiEnabled =
                         Settings.Global.getInt(
                                 mContext.getContentResolver(),
-                                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, 0) == 1;
-                if (!mScoringEnabled) {
-                    mScoreCache.clearScores();
-                }
+                                Settings.Global.NETWORK_SCORING_UI_ENABLED, 0) == 1;
             }
         };
-        ContentResolver cr = mContext.getContentResolver();
-        cr.registerContentObserver(
-                Settings.Global.getUriFor(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED),
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.NETWORK_SCORING_UI_ENABLED),
                 false /* notifyForDescendants */,
                 observer);
-        observer.onChange(false /* selfChange */);
-        registerScoreCache();
+
+        observer.onChange(false /* selfChange */); // Set the initial values
     }
 
     private void registerScoreCache() {
@@ -199,7 +200,7 @@
      * <p>{@link #updateScoreCacheIfNecessary} should be called prior to this method.
      */
     private int getWifiBadgeEnum() {
-        if (!mScoringEnabled || mWifiTracker.networkKey == null) {
+        if (!mScoringUiEnabled || mWifiTracker.networkKey == null) {
             return ScoredNetwork.BADGING_NONE;
         }
         ScoredNetwork score = mScoreCache.getScoredNetwork(mWifiTracker.networkKey);
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 395e8f2..85b1c32 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -63,14 +63,15 @@
 import com.android.systemui.R;
 import com.android.systemui.SwipeHelper;
 import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowProvider.MenuItem;
 import com.android.systemui.statusbar.ActivatableNotificationView;
 import com.android.systemui.statusbar.DismissView;
 import com.android.systemui.statusbar.EmptyShadeView;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.ExpandableView;
 import com.android.systemui.statusbar.NotificationGuts;
-import com.android.systemui.statusbar.NotificationSettingsIconRow;
-import com.android.systemui.statusbar.NotificationSettingsIconRow.SettingsIconRowListener;
+import com.android.systemui.statusbar.NotificationMenuRow;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.StackScrollerDecorView;
 import com.android.systemui.statusbar.StatusBarState;
@@ -78,7 +79,7 @@
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.ScrollAdapter;
@@ -94,7 +95,8 @@
 public class NotificationStackScrollLayout extends ViewGroup
         implements SwipeHelper.Callback, ExpandHelper.Callback, ScrollAdapter,
         ExpandableView.OnHeightChangedListener, NotificationGroupManager.OnGroupChangeListener,
-        SettingsIconRowListener, ScrollContainer, VisibilityLocationProvider {
+        NotificationMenuRowProvider.OnMenuClickListener, ScrollContainer,
+        VisibilityLocationProvider {
 
     public static final float BACKGROUND_ALPHA_DIMMED = 0.7f;
     private static final String TAG = "StackScroller";
@@ -224,7 +226,7 @@
     private int mMaxScrollAfterExpand;
     private SwipeHelper.LongPressListener mLongPressListener;
 
-    private NotificationSettingsIconRow mCurrIconRow;
+    private NotificationMenuRow mCurrIconRow;
     private View mTranslatingParentView;
     private View mGearExposedView;
 
@@ -249,7 +251,7 @@
             return true;
         }
     };
-    private PhoneStatusBar mPhoneStatusBar;
+    private StatusBar mStatusBar;
     private int[] mTempInt2 = new int[2];
     private boolean mGenerateChildOrderChangedEvent;
     private HashSet<Runnable> mAnimationFinishedRunnables = new HashSet<>();
@@ -399,16 +401,20 @@
     }
 
     @Override
-    public void onGearTouched(ExpandableNotificationRow row, int x, int y) {
-        if (mLongPressListener != null) {
+    public void onMenuClicked(View view, int x, int y, MenuItem item) {
+        if (mLongPressListener == null) {
+            return;
+        }
+        if (view instanceof ExpandableNotificationRow) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) view;
             MetricsLogger.action(mContext, MetricsEvent.ACTION_TOUCH_GEAR,
                     row.getStatusBarNotification().getPackageName());
-            mLongPressListener.onLongPress(row, x, y);
         }
+        mLongPressListener.onLongPress(view, x, y, item);
     }
 
     @Override
-    public void onSettingsIconRowReset(ExpandableNotificationRow row) {
+    public void onMenuReset(View row) {
         if (mTranslatingParentView != null && row == mTranslatingParentView) {
             mSwipeHelper.setSnappedToGear(false);
             mGearExposedView = null;
@@ -425,7 +431,7 @@
         if (DEBUG) {
             int y = mTopPadding;
             canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
-            y = (int) getLayoutHeight();
+            y = getLayoutHeight();
             canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
             y = getHeight() - getEmptyBottomMargin();
             canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
@@ -606,9 +612,9 @@
             ExpandableView child = (ExpandableView) getChildAt(i);
             if (mChildrenToAddAnimated.contains(child)) {
                 int startingPosition = getPositionInLinearLayout(child);
-                int padding = child.getIncreasedPaddingAmount() == 1.0f
-                        ? mIncreasedPaddingBetweenElements :
-                        mPaddingBetweenElements;
+                float increasedPaddingAmount = child.getIncreasedPaddingAmount();
+                int padding = increasedPaddingAmount == 1.0f ? mIncreasedPaddingBetweenElements
+                        : increasedPaddingAmount == -1.0f ? 0 : mPaddingBetweenElements;
                 int childHeight = getIntrinsicHeight(child) + padding;
                 if (startingPosition < mOwnScrollY) {
                     // This child starts off screen, so let's keep it offscreen to keep the others visible
@@ -871,7 +877,7 @@
 
         mFalsingManager.onNotificationDismissed();
         if (mFalsingManager.shouldEnforceBouncer()) {
-            mPhoneStatusBar.executeRunnableDismissingKeyguard(null, null /* cancelAction */,
+            mStatusBar.executeRunnableDismissingKeyguard(null, null /* cancelAction */,
                     false /* dismissShade */, true /* afterKeyguardGone */, false /* deferred */);
         }
     }
@@ -911,7 +917,7 @@
             mDragAnimPendingChildren.remove(animView);
         }
         if (mCurrIconRow != null && targetLeft == 0) {
-            mCurrIconRow.resetState();
+            mCurrIconRow.resetState(true /* notify */);
             mCurrIconRow = null;
         }
     }
@@ -962,7 +968,7 @@
 
     @Override
     public float getFalsingThresholdFactor() {
-        return mPhoneStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
+        return mStatusBar.isWakeUpComingFromTouch() ? 1.5f : 1.0f;
     }
 
     @Override
@@ -1880,7 +1886,8 @@
 
     private void updateContentHeight() {
         int height = 0;
-        float previousIncreasedAmount = 0.0f;
+        float previousPaddingRequest = mPaddingBetweenElements;
+        float previousPaddingAmount = 0.0f;
         int numShownItems = 0;
         boolean finish = false;
         int maxDisplayedNotifications = mAmbientState.isDark()
@@ -1897,13 +1904,35 @@
                     finish = true;
                 }
                 float increasedPaddingAmount = expandableView.getIncreasedPaddingAmount();
-                if (height != 0) {
-                    height += (int) NotificationUtils.interpolate(
+                float padding;
+                if (increasedPaddingAmount >= 0.0f) {
+                    padding = (int) NotificationUtils.interpolate(
+                            previousPaddingRequest,
+                            mIncreasedPaddingBetweenElements,
+                            increasedPaddingAmount);
+                    previousPaddingRequest = (int) NotificationUtils.interpolate(
                             mPaddingBetweenElements,
                             mIncreasedPaddingBetweenElements,
-                            Math.max(previousIncreasedAmount, increasedPaddingAmount));
+                            increasedPaddingAmount);
+                } else {
+                    int ownPadding = (int) NotificationUtils.interpolate(
+                            0,
+                            mPaddingBetweenElements,
+                            1.0f + increasedPaddingAmount);
+                    if (previousPaddingAmount > 0.0f) {
+                        padding = (int) NotificationUtils.interpolate(
+                                ownPadding,
+                                mIncreasedPaddingBetweenElements,
+                                previousPaddingAmount);
+                    } else {
+                        padding = ownPadding;
+                    }
+                    previousPaddingRequest = ownPadding;
                 }
-                previousIncreasedAmount = increasedPaddingAmount;
+                if (height != 0) {
+                    height += padding;
+                }
+                previousPaddingAmount = increasedPaddingAmount;
                 height += expandableView.getIntrinsicHeight();
                 numShownItems++;
                 if (finish) {
@@ -2566,10 +2595,19 @@
      */
     private void updateScrollStateForRemovedChild(ExpandableView removedChild) {
         int startingPosition = getPositionInLinearLayout(removedChild);
-        int padding = (int) NotificationUtils.interpolate(
-                mPaddingBetweenElements,
-                mIncreasedPaddingBetweenElements,
-                removedChild.getIncreasedPaddingAmount());
+        float increasedPaddingAmount = removedChild.getIncreasedPaddingAmount();
+        int padding;
+        if (increasedPaddingAmount >= 0) {
+            padding = (int) NotificationUtils.interpolate(
+                    mPaddingBetweenElements,
+                    mIncreasedPaddingBetweenElements,
+                    increasedPaddingAmount);
+        } else {
+            padding = (int) NotificationUtils.interpolate(
+                    0,
+                    mPaddingBetweenElements,
+                    1.0f + increasedPaddingAmount);
+        }
         int childHeight = getIntrinsicHeight(removedChild) + padding;
         int endPosition = startingPosition + childHeight;
         if (endPosition <= mOwnScrollY) {
@@ -2601,19 +2639,42 @@
             requestedView = requestedRow = childInGroup.getNotificationParent();
         }
         int position = 0;
-        float previousIncreasedAmount = 0.0f;
+        float previousPaddingRequest = mPaddingBetweenElements;
+        float previousPaddingAmount = 0.0f;
         for (int i = 0; i < getChildCount(); i++) {
             ExpandableView child = (ExpandableView) getChildAt(i);
             boolean notGone = child.getVisibility() != View.GONE;
             if (notGone && !child.hasNoContentHeight()) {
                 float increasedPaddingAmount = child.getIncreasedPaddingAmount();
-                if (position != 0) {
-                    position += (int) NotificationUtils.interpolate(
+                float padding;
+                if (increasedPaddingAmount >= 0.0f) {
+                    padding = (int) NotificationUtils.interpolate(
+                            previousPaddingRequest,
+                            mIncreasedPaddingBetweenElements,
+                            increasedPaddingAmount);
+                    previousPaddingRequest = (int) NotificationUtils.interpolate(
                             mPaddingBetweenElements,
                             mIncreasedPaddingBetweenElements,
-                            Math.max(previousIncreasedAmount, increasedPaddingAmount));
+                            increasedPaddingAmount);
+                } else {
+                    int ownPadding = (int) NotificationUtils.interpolate(
+                            0,
+                            mPaddingBetweenElements,
+                            1.0f + increasedPaddingAmount);
+                    if (previousPaddingAmount > 0.0f) {
+                        padding = (int) NotificationUtils.interpolate(
+                                ownPadding,
+                                mIncreasedPaddingBetweenElements,
+                                previousPaddingAmount);
+                    } else {
+                        padding = ownPadding;
+                    }
+                    previousPaddingRequest = ownPadding;
                 }
-                previousIncreasedAmount = increasedPaddingAmount;
+                if (position != 0) {
+                    position += padding;
+                }
+                previousPaddingAmount = increasedPaddingAmount;
             }
             if (child == requestedView) {
                 if (requestedRow != null) {
@@ -3161,7 +3222,7 @@
         mAmbientState.setExpansionChanging(false);
         if (!mIsExpanded) {
             setOwnScrollY(0);
-            mPhoneStatusBar.resetUserExpandedStates();
+            mStatusBar.resetUserExpandedStates();
 
             // lets make sure nothing is in the overlay / transient anymore
             clearTemporaryViews(this);
@@ -3696,8 +3757,8 @@
         return max + getStackTranslation();
     }
 
-    public void setPhoneStatusBar(PhoneStatusBar phoneStatusBar) {
-        this.mPhoneStatusBar = phoneStatusBar;
+    public void setStatusBar(StatusBar statusBar) {
+        this.mStatusBar = statusBar;
     }
 
     public void setGroupManager(NotificationGroupManager groupManager) {
@@ -3768,7 +3829,7 @@
 
     @Override
     public void onGroupCreatedFromChildren(NotificationGroupManager.NotificationGroup group) {
-        mPhoneStatusBar.requestNotificationUpdate();
+        mStatusBar.requestNotificationUpdate();
     }
 
     /** @hide */
@@ -3836,7 +3897,7 @@
 
     @Override
     public void onGroupsChanged() {
-        mPhoneStatusBar.requestNotificationUpdate();
+        mStatusBar.requestNotificationUpdate();
     }
 
     public void generateChildOrderChangedEvent() {
@@ -4121,7 +4182,7 @@
             if (currView instanceof ExpandableNotificationRow) {
                 // Set the listener for the current row's gear
                 mCurrIconRow = ((ExpandableNotificationRow) currView).getSettingsRow();
-                mCurrIconRow.setGearListener(NotificationStackScrollLayout.this);
+                mCurrIconRow.setMenuClickListener(NotificationStackScrollLayout.this);
             }
         }
 
@@ -4133,9 +4194,9 @@
                 mCurrIconRow.setSnapping(false); // If we're moving, we're not snapping.
 
                 // If the gear is visible and the movement is towards it it's not a location change.
-                boolean onLeft = mGearSnappedTo ? mGearSnappedOnLeft : mCurrIconRow.isIconOnLeft();
+                boolean onLeft = mGearSnappedTo ? mGearSnappedOnLeft : mCurrIconRow.isMenuOnLeft();
                 boolean locationChange = isTowardsGear(translation, onLeft)
-                        ? false : mCurrIconRow.isIconLocationChange(translation);
+                        ? false : mCurrIconRow.isMenuLocationChange(translation);
                 if (locationChange) {
                     // Don't consider it "snapped" if location has changed.
                     setSnappedToGear(false);
@@ -4146,8 +4207,8 @@
                         mCheckForDrag = null;
                     } else {
                         // Check scheduled, reset alpha and update location; check will fade it in
-                        mCurrIconRow.setGearAlpha(0f);
-                        mCurrIconRow.setIconLocation(translation > 0 /* onLeft */);
+                        mCurrIconRow.setMenuAlpha(0f);
+                        mCurrIconRow.setMenuLocation((int) translation);
                     }
                 }
             }
@@ -4198,14 +4259,14 @@
                 return false; // Let SwipeHelper handle it.
             }
 
-            boolean gestureTowardsGear = isTowardsGear(velocity, mCurrIconRow.isIconOnLeft());
+            boolean gestureTowardsGear = isTowardsGear(velocity, mCurrIconRow.isMenuOnLeft());
             boolean gestureFastEnough = Math.abs(velocity) > getEscapeVelocity();
             final double timeForGesture = ev.getEventTime() - ev.getDownTime();
             final boolean showGearForSlowOnGoing = !canChildBeDismissed(animView)
                 && timeForGesture >= SWIPE_GEAR_TIMING;
 
             if (mGearSnappedTo && mCurrIconRow.isVisible()) {
-                if (mGearSnappedOnLeft == mCurrIconRow.isIconOnLeft()) {
+                if (mGearSnappedOnLeft == mCurrIconRow.isMenuOnLeft()) {
                     boolean coveringGear =
                             Math.abs(getTranslation(animView)) <= getSpaceForGear(animView) * 0.6f;
                     if (gestureTowardsGear || coveringGear) {
@@ -4249,7 +4310,7 @@
 
         private void snapToGear(View animView, float velocity) {
             final float snapBackThreshold = getSpaceForGear(animView);
-            final float target = mCurrIconRow.isIconOnLeft() ? snapBackThreshold
+            final float target = mCurrIconRow.isMenuOnLeft() ? snapBackThreshold
                     : -snapBackThreshold;
             mGearExposedView = mTranslatingParentView;
             if (animView instanceof ExpandableNotificationRow) {
@@ -4280,7 +4341,7 @@
             final float multiplier = canChildBeDismissed(animView) ? 0.4f : 0.2f;
             final float snapBackThreshold = getSpaceForGear(animView) * multiplier;
             final float translation = getTranslation(animView);
-            return !swipedFarEnough() && mCurrIconRow.isVisible() && (mCurrIconRow.isIconOnLeft()
+            return !swipedFarEnough() && mCurrIconRow.isVisible() && (mCurrIconRow.isMenuOnLeft()
                     ? translation > snapBackThreshold
                     : translation < -snapBackThreshold);
         }
@@ -4306,7 +4367,7 @@
         }
 
         public void closeControlsIfOutsideTouch(MotionEvent ev) {
-            NotificationGuts guts = mPhoneStatusBar.getExposedGuts();
+            NotificationGuts guts = mStatusBar.getExposedGuts();
             View view = null;
             int height = 0;
             if (guts != null) {
@@ -4329,7 +4390,7 @@
                 Rect rect = new Rect(x, y, x + view.getWidth(), y + height);
                 if (!rect.contains(rx, ry)) {
                     // Touch was outside visible guts / gear notification, close what's visible
-                    mPhoneStatusBar.dismissPopups(-1, -1, true /* resetGear */, true /* animate */);
+                    mStatusBar.dismissPopups(-1, -1, true /* resetGear */, true /* animate */);
                 }
             }
         }
@@ -4349,7 +4410,7 @@
          * Indicates the the gear has been snapped to.
          */
         private void setSnappedToGear(boolean snapped) {
-            mGearSnappedOnLeft = (mCurrIconRow != null) ? mCurrIconRow.isIconOnLeft() : false;
+            mGearSnappedOnLeft = (mCurrIconRow != null) ? mCurrIconRow.isMenuOnLeft() : false;
             mGearSnappedTo = snapped && mCurrIconRow != null;
         }
 
@@ -4389,11 +4450,11 @@
                 final float bounceBackToGearWidth = getSpaceForGear(mTranslatingParentView);
                 final float notiThreshold = getSize(mTranslatingParentView) * 0.4f;
                 if ((mCurrIconRow != null && (!mCurrIconRow.isVisible()
-                        || mCurrIconRow.isIconLocationChange(translation)))
+                        || mCurrIconRow.isMenuLocationChange(translation)))
                         && absTransX >= bounceBackToGearWidth * 0.4
                         && absTransX < notiThreshold) {
                     // Fade in the gear
-                    mCurrIconRow.fadeInSettings(translation > 0 /* fromLeft */, translation,
+                    mCurrIconRow.fadeInMenu(translation > 0 /* fromLeft */, translation,
                             notiThreshold);
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 7ff1000..ba91ffd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -27,7 +27,6 @@
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.ExpandableView;
 import com.android.systemui.statusbar.NotificationShelf;
-import com.android.systemui.statusbar.StackScrollerDecorView;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 
 import java.util.ArrayList;
@@ -244,7 +243,7 @@
         int childCount = hostView.getChildCount();
         state.visibleChildren.clear();
         state.visibleChildren.ensureCapacity(childCount);
-        state.increasedPaddingMap.clear();
+        state.paddingMap.clear();
         int notGoneIndex = 0;
         ExpandableView lastView = null;
         for (int i = 0; i < childCount; i++) {
@@ -254,16 +253,31 @@
                     continue;
                 }
                 notGoneIndex = updateNotGoneIndex(resultState, state, notGoneIndex, v);
-                float increasedPadding = v.getIncreasedPaddingAmount();
+                float increasedPadding = v.getIncreasedPaddingAmount();;
                 if (increasedPadding != 0.0f) {
-                    state.increasedPaddingMap.put(v, increasedPadding);
+                    state.paddingMap.put(v, increasedPadding);
                     if (lastView != null) {
-                        Float prevValue = state.increasedPaddingMap.get(lastView);
-                        float newValue = prevValue != null
-                                ? Math.max(prevValue, increasedPadding)
-                                : increasedPadding;
-                        state.increasedPaddingMap.put(lastView, newValue);
+                        Float prevValue = state.paddingMap.get(lastView);
+                        float newValue = getPaddingForValue(increasedPadding);
+                        if (prevValue != null) {
+                            float prevPadding = getPaddingForValue(prevValue);
+                            if (increasedPadding > 0) {
+                                newValue = NotificationUtils.interpolate(
+                                        prevPadding,
+                                        newValue,
+                                        increasedPadding);
+                            } else if (prevValue > 0) {
+                                newValue = NotificationUtils.interpolate(
+                                        newValue,
+                                        prevPadding,
+                                        prevValue);
+                            }
+                        }
+                        state.paddingMap.put(lastView, newValue);
                     }
+                } else if (lastView != null) {
+                    float newValue = getPaddingForValue(state.paddingMap.get(lastView));
+                    state.paddingMap.put(lastView, newValue);
                 }
                 if (v instanceof ExpandableNotificationRow) {
                     ExpandableNotificationRow row = (ExpandableNotificationRow) v;
@@ -287,6 +301,22 @@
         }
     }
 
+    private float getPaddingForValue(Float increasedPadding) {
+        if (increasedPadding == null) {
+            return mPaddingBetweenElements;
+        } else if (increasedPadding >= 0.0f) {
+            return NotificationUtils.interpolate(
+                    mPaddingBetweenElements,
+                    mIncreasedPaddingBetweenElements,
+                    increasedPadding);
+        } else {
+            return NotificationUtils.interpolate(
+                    0,
+                    mPaddingBetweenElements,
+                    1.0f + increasedPadding);
+        }
+    }
+
     private int updateNotGoneIndex(StackScrollState resultState,
             StackScrollAlgorithmState state, int notGoneIndex,
             ExpandableView v) {
@@ -527,18 +557,17 @@
         public final ArrayList<ExpandableView> visibleChildren = new ArrayList<ExpandableView>();
 
         /**
-         * The children from the host that need an increased padding after them. A value of 0 means
-         * no increased padding, a value of 1 means full padding.
+         * The padding after each child measured in pixels.
          */
-        public final HashMap<ExpandableView, Float> increasedPaddingMap = new HashMap<>();
+        public final HashMap<ExpandableView, Float> paddingMap = new HashMap<>();
 
         public int getPaddingAfterChild(ExpandableView child) {
-            Float paddingValue = increasedPaddingMap.get(child);
-            return paddingValue == null
-                    ? mPaddingBetweenElements
-                    : (int) NotificationUtils.interpolate(mPaddingBetweenElements,
-                            mIncreasedPaddingBetweenElements,
-                            paddingValue);
+            Float padding = paddingMap.get(child);
+            if (padding == null) {
+                // Should only happen for the last view
+                return mPaddingBetweenElements;
+            }
+            return (int) padding.floatValue();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 9b8183b..ab562d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -17,23 +17,29 @@
 package com.android.systemui.statusbar.tv;
 
 import android.content.ComponentName;
+import android.content.Context;
 import android.graphics.Rect;
 import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.service.notification.NotificationListenerService.RankingMap;
-import android.service.notification.StatusBarNotification;
-import android.view.View;
 
+import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.StatusBarIcon;
-import com.android.systemui.statusbar.ActivatableNotificationView;
-import com.android.systemui.statusbar.BaseStatusBar;
-import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.SystemUI;
 import com.android.systemui.pip.tv.PipManager;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.CommandQueue.Callbacks;
+
+import java.util.ArrayList;
 
 /**
  * Status bar implementation for "large screen" products that mostly present no on-screen nav
  */
 
-public class TvStatusBar extends BaseStatusBar {
+public class TvStatusBar extends SystemUI implements Callbacks {
+
+    private IStatusBarService mBarService;
 
     @Override
     public void setIcon(String slot, StatusBarIcon icon) {
@@ -43,16 +49,6 @@
     public void removeIcon(String slot) {
     }
 
-    @Override
-    public void addNotification(StatusBarNotification notification, RankingMap ranking,
-            NotificationData.Entry entry) {
-    }
-
-    @Override
-    protected void updateNotificationRanking(RankingMap ranking) {
-    }
-
-    @Override
     public void removeNotification(String key, RankingMap ranking) {
     }
 
@@ -99,53 +95,10 @@
     }
 
     @Override
-    protected void setAreThereNotifications() {
-    }
-
-    @Override
-    protected void updateNotifications() {
-    }
-
-    public View getStatusBarView() {
-        return null;
-    }
-
-    @Override
-    protected boolean toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction) {
-        return false;
-    }
-
-    @Override
-    public void maybeEscalateHeadsUp() {
-    }
-
-    @Override
-    public boolean isPanelFullyCollapsed() {
-        return false;
-    }
-
-    @Override
-    protected int getMaxKeyguardNotifications(boolean recompute) {
-        return 0;
-    }
-
-    @Override
     public void animateExpandSettingsPanel(String subPanel) {
     }
 
     @Override
-    protected void createAndAddWindows() {
-    }
-
-    @Override
-    public void onActivated(ActivatableNotificationView view) {
-    }
-
-    @Override
-    public void onActivationReset(ActivatableNotificationView view) {
-    }
-
-    @Override
     public void showScreenPinningRequest(int taskId) {
     }
 
@@ -175,19 +128,6 @@
     }
 
     @Override
-    protected void updateHeadsUp(String key, NotificationData.Entry entry, boolean shouldPeek,
-            boolean alertAgain) {
-    }
-
-    @Override
-    protected void setHeadsUpUser(int newUserId) {
-    }
-
-    protected boolean isSnoozedPackage(StatusBarNotification sbn) {
-        return false;
-    }
-
-    @Override
     public void addQsTile(ComponentName tile) {
     }
 
@@ -201,8 +141,23 @@
 
     @Override
     public void start() {
-        super.start();
         putComponent(TvStatusBar.class, this);
+        CommandQueue commandQueue = getComponent(CommandQueue.class);
+        commandQueue.addCallbacks(this);
+        int[] switches = new int[9];
+        ArrayList<IBinder> binders = new ArrayList<>();
+        ArrayList<String> iconSlots = new ArrayList<>();
+        ArrayList<StatusBarIcon> icons = new ArrayList<>();
+        Rect fullscreenStackBounds = new Rect();
+        Rect dockedStackBounds = new Rect();
+        mBarService = IStatusBarService.Stub.asInterface(
+                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+        try {
+            mBarService.registerStatusBar(commandQueue, iconSlots, icons, switches, binders,
+                    fullscreenStackBounds, dockedStackBounds);
+        } catch (RemoteException ex) {
+            // If the system process isn't there we're doomed anyway.
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/BetterListPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/BetterListPreference.java
new file mode 100644
index 0000000..c9c780a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/BetterListPreference.java
@@ -0,0 +1,39 @@
+/*
+ * 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.tuner;
+
+import android.content.Context;
+import android.support.v7.preference.ListPreference;
+import android.util.AttributeSet;
+
+public class BetterListPreference extends ListPreference {
+
+    private CharSequence mSummary;
+
+    public BetterListPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public void setSummary(CharSequence summary) {
+        super.setSummary(summary);
+        mSummary = summary;
+    }
+
+    @Override
+    public CharSequence getSummary() {
+        return mSummary;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
new file mode 100644
index 0000000..41786b5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
@@ -0,0 +1,404 @@
+/*
+ * 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.tuner;
+
+import android.app.AlertDialog;
+import android.app.AlertDialog.Builder;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.LauncherActivityInfo;
+import android.content.pm.LauncherApps;
+import android.content.pm.LauncherApps.ShortcutQuery;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ShortcutInfo;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Process;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceGroup;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.ViewHolder;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.plugins.IntentButtonProvider.IntentButton;
+import com.android.systemui.statusbar.phone.ExpandableIndicator;
+import com.android.systemui.tuner.ShortcutParser.Shortcut;
+import com.android.systemui.tuner.TunerService.Tunable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+
+public class LockscreenFragment extends PreferenceFragment {
+
+    private static final String KEY_LEFT = "left";
+    private static final String KEY_RIGHT = "right";
+    private static final String KEY_CUSTOMIZE = "customize";
+    private static final String KEY_SHORTCUT = "shortcut";
+
+    public static final String LOCKSCREEN_LEFT_BUTTON = "sysui_keyguard_left";
+    public static final String LOCKSCREEN_LEFT_UNLOCK = "sysui_keyguard_left_unlock";
+    public static final String LOCKSCREEN_RIGHT_BUTTON = "sysui_keyguard_right";
+    public static final String LOCKSCREEN_RIGHT_UNLOCK = "sysui_keyguard_right_unlock";
+
+    private final ArrayList<Tunable> mTunables = new ArrayList<>();
+    private TunerService mTunerService;
+    private Handler mHandler;
+
+    @Override
+    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+        mTunerService = TunerService.get(getContext());
+        mHandler = new Handler();
+        addPreferencesFromResource(R.xml.lockscreen_settings);
+        setupGroup((PreferenceGroup) findPreference(KEY_LEFT), LOCKSCREEN_LEFT_BUTTON,
+                LOCKSCREEN_LEFT_UNLOCK);
+        setupGroup((PreferenceGroup) findPreference(KEY_RIGHT), LOCKSCREEN_RIGHT_BUTTON,
+                LOCKSCREEN_RIGHT_UNLOCK);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        mTunables.forEach(t -> mTunerService.removeTunable(t));
+    }
+
+    private void setupGroup(PreferenceGroup group, String buttonSetting, String unlockKey) {
+        SwitchPreference customize = (SwitchPreference) group.findPreference(KEY_CUSTOMIZE);
+        Preference shortcut = group.findPreference(KEY_SHORTCUT);
+        SwitchPreference unlock = (SwitchPreference) group.findPreference(unlockKey);
+        addTunable((k, v) -> {
+            boolean visible = v != null;
+            customize.setChecked(visible);
+            shortcut.setVisible(visible);
+            unlock.setVisible(visible);
+            if (visible) {
+                setSummary(shortcut, v);
+            }
+        }, buttonSetting);
+        customize.setOnPreferenceChangeListener((preference, newValue) -> {
+            boolean hasSetting = mTunerService.getValue(buttonSetting) != null;
+            if (hasSetting != (boolean) newValue) {
+                mHandler.post(() -> mTunerService.setValue(buttonSetting, hasSetting ? null : ""));
+            }
+            return true;
+        });
+        shortcut.setOnPreferenceClickListener(preference -> {
+            showSelectDialog(buttonSetting);
+            return true;
+        });
+    }
+
+    private void showSelectDialog(String buttonSetting) {
+        RecyclerView v = (RecyclerView) LayoutInflater.from(getContext())
+                .inflate(R.layout.tuner_shortcut_list, null);
+        v.setLayoutManager(new LinearLayoutManager(getContext()));
+        AlertDialog dialog = new Builder(getContext())
+                .setView(v)
+                .show();
+        Adapter adapter = new Adapter(getContext(), item -> {
+            mTunerService.setValue(buttonSetting, item.getSettingValue());
+            dialog.dismiss();
+        });
+        LauncherApps apps = getContext().getSystemService(LauncherApps.class);
+        List<LauncherActivityInfo> activities = apps.getActivityList(null,
+                Process.myUserHandle());
+
+        activities.forEach(info -> {
+            App app = new App(getContext(), info);
+            try {
+                new ShortcutParser(getContext(), info.getComponentName()).getShortcuts().forEach(
+                        shortcut -> app.addChild(new StaticShortcut(getContext(), shortcut)));
+            } catch (NameNotFoundException e) {
+            }
+            adapter.addItem(app);
+        });
+
+        v.setAdapter(adapter);
+    }
+
+    private void setSummary(Preference shortcut, String value) {
+        if (value.contains("::")) {
+            Shortcut info = getShortcutInfo(getContext(), value);
+            shortcut.setSummary(info != null ? info.label : null);
+        } else if (value.contains("/")) {
+            ActivityInfo info = getActivityinfo(getContext(), value);
+            shortcut.setSummary(info != null ? info.loadLabel(getContext().getPackageManager())
+                    : null);
+        } else {
+            shortcut.setSummary(null);
+        }
+    }
+
+    private void addTunable(Tunable t, String... keys) {
+        mTunables.add(t);
+        mTunerService.addTunable(t, keys);
+    }
+
+    public static ActivityInfo getActivityinfo(Context context, String value) {
+        ComponentName component = ComponentName.unflattenFromString(value);
+        try {
+            return context.getPackageManager().getActivityInfo(component, 0);
+        } catch (NameNotFoundException e) {
+            return null;
+        }
+    }
+
+    public static Shortcut getShortcutInfo(Context context, String value) {
+        return Shortcut.create(context, value);
+    }
+
+    public static class Holder extends ViewHolder {
+        public final ImageView icon;
+        public final TextView title;
+        public final ExpandableIndicator expand;
+
+        public Holder(View itemView) {
+            super(itemView);
+            icon = (ImageView) itemView.findViewById(android.R.id.icon);
+            title = (TextView) itemView.findViewById(android.R.id.title);
+            expand = (ExpandableIndicator) itemView.findViewById(R.id.expand);
+        }
+    }
+
+    private static class StaticShortcut extends Item {
+
+        private final Context mContext;
+        private final Shortcut mShortcut;
+
+
+        public StaticShortcut(Context context, Shortcut shortcut) {
+            mContext = context;
+            mShortcut = shortcut;
+        }
+
+        @Override
+        public Drawable getDrawable() {
+            return mShortcut.icon.loadDrawable(mContext);
+        }
+
+        @Override
+        public String getLabel() {
+            return mShortcut.label;
+        }
+
+        @Override
+        public String getSettingValue() {
+            return mShortcut.toString();
+        }
+
+        @Override
+        public Boolean getExpando() {
+            return null;
+        }
+    }
+
+    private static class App extends Item {
+
+        private final Context mContext;
+        private final LauncherActivityInfo mInfo;
+        private final ArrayList<Item> mChildren = new ArrayList<>();
+        private boolean mExpanded;
+
+        public App(Context context, LauncherActivityInfo info) {
+            mContext = context;
+            mInfo = info;
+            mExpanded = false;
+        }
+
+        public void addChild(Item child) {
+            mChildren.add(child);
+        }
+
+        @Override
+        public Drawable getDrawable() {
+            return mInfo.getBadgedIcon(mContext.getResources().getConfiguration().densityDpi);
+        }
+
+        @Override
+        public String getLabel() {
+            return mInfo.getLabel().toString();
+        }
+
+        @Override
+        public String getSettingValue() {
+            return mInfo.getComponentName().flattenToString();
+        }
+
+        @Override
+        public Boolean getExpando() {
+            return mChildren.size() != 0 ? mExpanded : null;
+        }
+
+        @Override
+        public void toggleExpando(Adapter adapter) {
+            mExpanded = !mExpanded;
+            if (mExpanded) {
+                mChildren.forEach(child -> adapter.addItem(this, child));
+            } else {
+                mChildren.forEach(child -> adapter.remItem(child));
+            }
+        }
+    }
+
+    private abstract static class Item {
+        public abstract Drawable getDrawable();
+
+        public abstract String getLabel();
+
+        public abstract String getSettingValue();
+
+        public abstract Boolean getExpando();
+
+        public void toggleExpando(Adapter adapter) {
+        }
+    }
+
+    public static class Adapter extends RecyclerView.Adapter<Holder> {
+        private ArrayList<Item> mItems = new ArrayList<>();
+        private final Context mContext;
+        private final Consumer<Item> mCallback;
+
+        public Adapter(Context context, Consumer<Item> callback) {
+            mContext = context;
+            mCallback = callback;
+        }
+
+        @Override
+        public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
+            return new Holder(LayoutInflater.from(parent.getContext())
+                    .inflate(R.layout.tuner_shortcut_item, parent, false));
+        }
+
+        @Override
+        public void onBindViewHolder(Holder holder, int position) {
+            Item item = mItems.get(position);
+            holder.icon.setImageDrawable(item.getDrawable());
+            holder.title.setText(item.getLabel());
+            holder.itemView.setOnClickListener(
+                    v -> mCallback.accept(mItems.get(holder.getAdapterPosition())));
+            Boolean expando = item.getExpando();
+            if (expando != null) {
+                holder.expand.setVisibility(View.VISIBLE);
+                holder.expand.setExpanded(expando);
+                holder.expand.setOnClickListener(
+                        v -> mItems.get(holder.getAdapterPosition()).toggleExpando(Adapter.this));
+            } else {
+                holder.expand.setVisibility(View.GONE);
+            }
+        }
+
+        @Override
+        public int getItemCount() {
+            return mItems.size();
+        }
+
+        public void addItem(Item item) {
+            mItems.add(item);
+            notifyDataSetChanged();
+        }
+
+        public void remItem(Item item) {
+            int index = mItems.indexOf(item);
+            mItems.remove(item);
+            notifyItemRemoved(index);
+        }
+
+        public void addItem(Item parent, Item child) {
+            int index = mItems.indexOf(parent);
+            mItems.add(index + 1, child);
+            notifyItemInserted(index + 1);
+        }
+    }
+
+    public static IntentButton getIntentButton(Context context, String buttonStr,
+            IntentButton plugin, IntentButton def) {
+        // Plugin wins.
+        if (plugin != null) return plugin;
+        // Then tuner options.
+        if (!TextUtils.isEmpty(buttonStr)) {
+            if (buttonStr.contains("::")) {
+                Shortcut shortcut = getShortcutInfo(context, buttonStr);
+                if (shortcut != null) {
+                    return new ShortcutButton(context, shortcut);
+                }
+            } else if (buttonStr.contains("/")) {
+                ActivityInfo info = getActivityinfo(context, buttonStr);
+                if (info != null) {
+                    return new ActivityButton(context, info);
+                }
+            }
+        }
+        // Then default.
+        return def;
+    }
+
+    private static class ShortcutButton implements IntentButton {
+        private final Shortcut mShortcut;
+        private final IconState mIconState;
+
+        public ShortcutButton(Context context, Shortcut shortcut) {
+            mShortcut = shortcut;
+            mIconState = new IconState();
+            mIconState.isVisible = true;
+            mIconState.drawable = shortcut.icon.loadDrawable(context);
+            mIconState.contentDescription = mShortcut.label;
+        }
+
+        @Override
+        public IconState getIcon() {
+            return mIconState;
+        }
+
+        @Override
+        public Intent getIntent() {
+            return mShortcut.intent;
+        }
+    }
+
+    private static class ActivityButton implements IntentButton {
+        private final Intent mIntent;
+        private final IconState mIconState;
+
+        public ActivityButton(Context context, ActivityInfo info) {
+            mIntent = new Intent().setComponent(new ComponentName(info.packageName, info.name));
+            mIconState = new IconState();
+            mIconState.isVisible = true;
+            mIconState.drawable = info.loadIcon(context.getPackageManager());
+            mIconState.contentDescription = info.loadLabel(context.getPackageManager());
+        }
+
+        @Override
+        public IconState getIcon() {
+            return mIconState;
+        }
+
+        @Override
+        public Intent getIntent() {
+            return mIntent;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
index ad42459..9593c45 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
@@ -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. You may obtain a copy of the License at
@@ -14,590 +14,227 @@
 
 package com.android.systemui.tuner;
 
-import android.annotation.Nullable;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Fragment;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.res.ColorStateList;
-import android.content.res.Configuration;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.helper.ItemTouchHelper;
-import android.util.TypedValue;
-import android.view.Display;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.Surface;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.SeekBar;
-import android.widget.TextView;
-
-import com.android.systemui.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.BACK;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.BUTTON_SEPARATOR;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.CLIPBOARD;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.GRAVITY_SEPARATOR;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.HOME;
 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY;
 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_CODE_END;
 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_CODE_START;
 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.KEY_IMAGE_DELIM;
 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.MENU_IME;
 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAVSPACE;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_LEFT;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_RIGHT;
 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_VIEWS;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.RECENT;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.SIZE_MOD_END;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.SIZE_MOD_START;
 import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.extractButton;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.extractSize;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.extractImage;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.extractKeycode;
 
-public class NavBarTuner extends Fragment implements TunerService.Tunable {
+import android.annotation.Nullable;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v14.preference.PreferenceFragment;
+import android.support.v7.preference.DropDownPreference;
+import android.support.v7.preference.ListPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.Preference.OnPreferenceChangeListener;
+import android.support.v7.preference.Preference.OnPreferenceClickListener;
+import android.support.v7.preference.PreferenceCategory;
+import android.text.SpannableStringBuilder;
+import android.text.style.ImageSpan;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.KeyEvent;
+import android.widget.EditText;
 
-    private static final int SAVE = Menu.FIRST + 1;
-    private static final int RESET = Menu.FIRST + 2;
-    private static final int READ_REQUEST = 42;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.NavigationBarInflaterView;
+import com.android.systemui.tuner.TunerService.Tunable;
 
-    private static final float PREVIEW_SCALE = .95f;
-    private static final float PREVIEW_SCALE_LANDSCAPE = .75f;
+import java.util.ArrayList;
 
-    private NavBarAdapter mNavBarAdapter;
-    private PreviewNavInflater mPreview;
+public class NavBarTuner extends PreferenceFragment {
+
+    private static final String LAYOUT = "layout";
+    private static final String LEFT = "left";
+    private static final String RIGHT = "right";
+
+    private static final String TYPE = "type";
+    private static final String KEYCODE = "keycode";
+    private static final String ICON = "icon";
+
+    private static final int[] ICONS = new int[]{
+            R.drawable.ic_qs_circle,
+            R.drawable.ic_add,
+            R.drawable.ic_remove,
+            R.drawable.ic_left,
+            R.drawable.ic_right,
+            R.drawable.ic_menu,
+    };
+
+    private final ArrayList<Tunable> mTunables = new ArrayList<>();
+    private Handler mHandler;
 
     @Override
-    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
-            Bundle savedInstanceState) {
-        final View view = inflater.inflate(R.layout.nav_bar_tuner, container, false);
-        inflatePreview((ViewGroup) view.findViewById(R.id.nav_preview_frame));
-        return view;
-    }
-
-    private void inflatePreview(ViewGroup view) {
-        Display display = getActivity().getWindowManager().getDefaultDisplay();
-        boolean isRotated = display.getRotation() == Surface.ROTATION_90
-                || display.getRotation() == Surface.ROTATION_270;
-
-        Configuration config = new Configuration(getContext().getResources().getConfiguration());
-        boolean isPhoneLandscape = isRotated && (config.smallestScreenWidthDp < 600);
-        final float scale = isPhoneLandscape ? PREVIEW_SCALE_LANDSCAPE : PREVIEW_SCALE;
-        config.densityDpi = (int) (config.densityDpi * scale);
-
-        mPreview = (PreviewNavInflater) LayoutInflater.from(getContext().createConfigurationContext(
-                config)).inflate(R.layout.nav_bar_tuner_inflater, view, false);
-        final ViewGroup.LayoutParams layoutParams = mPreview.getLayoutParams();
-        layoutParams.width = (int) ((isPhoneLandscape ? display.getHeight() : display.getWidth())
-                * scale);
-        // Not sure why, but the height dimen is not being scaled with the dp, set it manually
-        // for now.
-        layoutParams.height = (int) (layoutParams.height * scale);
-        if (isPhoneLandscape) {
-            int width = layoutParams.width;
-            layoutParams.width = layoutParams.height;
-            layoutParams.height = width;
-        }
-        view.addView(mPreview);
-
-        if (isRotated) {
-            mPreview.findViewById(R.id.rot0).setVisibility(View.GONE);
-            final View rot90 = mPreview.findViewById(R.id.rot90);
-        } else {
-            mPreview.findViewById(R.id.rot90).setVisibility(View.GONE);
-            final View rot0 = mPreview.findViewById(R.id.rot0);
-        }
-    }
-
-    private void notifyChanged() {
-        mPreview.onTuningChanged(NAV_BAR_VIEWS, mNavBarAdapter.getNavString());
+    public void onCreate(@Nullable Bundle savedInstanceState) {
+        mHandler = new Handler();
+        super.onCreate(savedInstanceState);
     }
 
     @Override
-    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
-        super.onViewCreated(view, savedInstanceState);
-        RecyclerView recyclerView = (RecyclerView) view.findViewById(android.R.id.list);
-        final Context context = getContext();
-        recyclerView.setLayoutManager(new LinearLayoutManager(context));
-        mNavBarAdapter = new NavBarAdapter(context);
-        recyclerView.setAdapter(mNavBarAdapter);
-        recyclerView.addItemDecoration(new Dividers(context));
-        final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(mNavBarAdapter.mCallbacks);
-        mNavBarAdapter.setTouchHelper(itemTouchHelper);
-        itemTouchHelper.attachToRecyclerView(recyclerView);
-
-        TunerService.get(getContext()).addTunable(this, NAV_BAR_VIEWS);
+    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
     }
 
     @Override
-    public void onDestroyView() {
-        super.onDestroyView();
-        TunerService.get(getContext()).removeTunable(this);
+    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+        addPreferencesFromResource(R.xml.nav_bar_tuner);
+        bindLayout((ListPreference) findPreference(LAYOUT));
+        bindButton((PreferenceCategory) findPreference(LEFT),
+                NAV_BAR_LEFT, NAVSPACE);
+        bindButton((PreferenceCategory) findPreference(RIGHT),
+                NAV_BAR_RIGHT, MENU_IME);
     }
 
     @Override
-    public void onTuningChanged(String key, String navLayout) {
-        if (!NAV_BAR_VIEWS.equals(key)) return;
-        Context context = getContext();
-        if (navLayout == null) {
-            navLayout = context.getString(R.string.config_navBarLayout);
-        }
-        String[] views = navLayout.split(GRAVITY_SEPARATOR);
-        String[] groups = new String[] { NavBarAdapter.START, NavBarAdapter.CENTER,
-                NavBarAdapter.END};
-        CharSequence[] groupLabels = new String[] { getString(R.string.start),
-                getString(R.string.center), getString(R.string.end) };
-        mNavBarAdapter.clear();
-        for (int i = 0; i < 3; i++) {
-            mNavBarAdapter.addButton(groups[i], groupLabels[i]);
-            for (String button : views[i].split(BUTTON_SEPARATOR)) {
-                mNavBarAdapter.addButton(button, getLabel(button, context));
+    public void onDestroy() {
+        super.onDestroy();
+        mTunables.forEach(t -> TunerService.get(getContext()).removeTunable(t));
+    }
+
+    private void addTunable(Tunable tunable, String... keys) {
+        mTunables.add(tunable);
+        TunerService.get(getContext()).addTunable(tunable, keys);
+    }
+
+    private void bindLayout(ListPreference preference) {
+        addTunable((key, newValue) -> mHandler.post(() -> {
+            String val = newValue;
+            if (val == null) {
+                val = "default";
             }
-        }
-        mNavBarAdapter.addButton(NavBarAdapter.ADD, getString(R.string.add_button));
-        setHasOptionsMenu(true);
+            preference.setValue(val);
+        }), NAV_BAR_VIEWS);
+        preference.setOnPreferenceChangeListener((preference1, newValue) -> {
+            String val = (String) newValue;
+            if ("default".equals(val)) val = null;
+            TunerService.get(getContext()).setValue(NAV_BAR_VIEWS, val);
+            return true;
+        });
     }
 
-    @Override
-    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
-        super.onCreateOptionsMenu(menu, inflater);
-        // TODO: Show save button conditionally, only when there are changes.
-        menu.add(Menu.NONE, SAVE, Menu.NONE, getString(R.string.save))
-                .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
-        menu.add(Menu.NONE, RESET, Menu.NONE, getString(R.string.reset));
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        if (item.getItemId() == SAVE) {
-            if (!mNavBarAdapter.hasHomeButton()) {
-                new AlertDialog.Builder(getContext())
-                        .setTitle(R.string.no_home_title)
-                        .setMessage(R.string.no_home_message)
-                        .setPositiveButton(android.R.string.ok, null)
-                        .show();
+    private void bindButton(PreferenceCategory parent, String setting, String def) {
+        String k = parent.getKey();
+        DropDownPreference type = (DropDownPreference) findPreference(TYPE + "_" + k);
+        Preference keycode = findPreference(KEYCODE + "_" + k);
+        ListPreference icon = (ListPreference) findPreference(ICON + "_" + k);
+        setupIcons(icon);
+        addTunable((key, newValue) -> mHandler.post(() -> {
+            String val = newValue;
+            if (val == null) {
+                val = def;
+            }
+            String button = extractButton(val);
+            if (button.startsWith(KEY)) {
+                type.setValue(KEY);
+                String uri = extractImage(button);
+                int code = extractKeycode(button);
+                icon.setValue(uri);
+                updateSummary(icon);
+                keycode.setSummary(code + "");
+                keycode.setVisible(true);
+                icon.setVisible(true);
             } else {
-                Settings.Secure.putString(getContext().getContentResolver(),
-                        NAV_BAR_VIEWS, mNavBarAdapter.getNavString());
+                type.setValue(button);
+                keycode.setVisible(false);
+                icon.setVisible(false);
             }
-            return true;
-        } else if (item.getItemId() == RESET) {
-            Settings.Secure.putString(getContext().getContentResolver(),
-                    NAV_BAR_VIEWS, null);
-            return true;
-        }
-        return super.onOptionsItemSelected(item);
-    }
-
-    private static CharSequence getLabel(String button, Context context) {
-        if (button.startsWith(HOME)) {
-            return context.getString(R.string.accessibility_home);
-        } else if (button.startsWith(BACK)) {
-            return context.getString(R.string.accessibility_back);
-        } else if (button.startsWith(RECENT)) {
-            return context.getString(R.string.accessibility_recent);
-        } else if (button.startsWith(NAVSPACE)) {
-            return context.getString(R.string.space);
-        } else if (button.startsWith(MENU_IME)) {
-            return context.getString(R.string.menu_ime);
-        } else if (button.startsWith(CLIPBOARD)) {
-            return context.getString(R.string.clipboard);
-        } else if (button.startsWith(KEY)) {
-            return context.getString(R.string.keycode);
-        }
-        return button;
-    }
-
-    private static class Holder extends RecyclerView.ViewHolder {
-        private TextView title;
-
-        public Holder(View itemView) {
-            super(itemView);
-            title = (TextView) itemView.findViewById(android.R.id.title);
-        }
-    }
-
-    private static class Dividers extends RecyclerView.ItemDecoration {
-        private final Drawable mDivider;
-
-        public Dividers(Context context) {
-            TypedValue value = new TypedValue();
-            context.getTheme().resolveAttribute(android.R.attr.listDivider, value, true);
-            mDivider = context.getDrawable(value.resourceId);
-        }
-
-        @Override
-        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
-            super.onDraw(c, parent, state);
-            final int left = parent.getPaddingLeft();
-            final int right = parent.getWidth() - parent.getPaddingRight();
-
-            final int childCount = parent.getChildCount();
-            for (int i = 0; i < childCount; i++) {
-                final View child = parent.getChildAt(i);
-                final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
-                        .getLayoutParams();
-                final int top = child.getBottom() + params.bottomMargin;
-                final int bottom = top + mDivider.getIntrinsicHeight();
-                mDivider.setBounds(left, top, right, bottom);
-                mDivider.draw(c);
-            }
-        }
-    }
-
-    private void selectImage() {
-        startActivityForResult(KeycodeSelectionHelper.getSelectImageIntent(), READ_REQUEST);
-    }
-
-    @Override
-    public void onActivityResult(int requestCode, int resultCode, Intent data) {
-        if (requestCode == READ_REQUEST && resultCode == Activity.RESULT_OK && data != null) {
-            final Uri uri = data.getData();
-            final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION);
-            getContext().getContentResolver().takePersistableUriPermission(uri, takeFlags);
-            mNavBarAdapter.onImageSelected(uri);
-        } else {
-            super.onActivityResult(requestCode, resultCode, data);
-        }
-    }
-
-    private class NavBarAdapter extends RecyclerView.Adapter<Holder>
-            implements View.OnClickListener {
-
-        private static final String START = "start";
-        private static final String CENTER = "center";
-        private static final String END = "end";
-        private static final String ADD = "add";
-
-        private static final int ADD_ID = 0;
-        private static final int BUTTON_ID = 1;
-        private static final int CATEGORY_ID = 2;
-
-        private List<String> mButtons = new ArrayList<>();
-        private List<CharSequence> mLabels = new ArrayList<>();
-        private int mCategoryLayout;
-        private int mButtonLayout;
-        private ItemTouchHelper mTouchHelper;
-
-        // Stored keycode while we wait for image selection on a KEY.
-        private int mKeycode;
-
-        public NavBarAdapter(Context context) {
-            TypedArray attrs = context.getTheme().obtainStyledAttributes(null,
-                    android.R.styleable.Preference, android.R.attr.preferenceStyle, 0);
-            mButtonLayout = attrs.getResourceId(android.R.styleable.Preference_layout, 0);
-            attrs = context.getTheme().obtainStyledAttributes(null,
-                    android.R.styleable.Preference, android.R.attr.preferenceCategoryStyle, 0);
-            mCategoryLayout = attrs.getResourceId(android.R.styleable.Preference_layout, 0);
-        }
-
-        public void setTouchHelper(ItemTouchHelper itemTouchHelper) {
-            mTouchHelper = itemTouchHelper;
-        }
-
-        public void clear() {
-            mButtons.clear();
-            mLabels.clear();
-            notifyDataSetChanged();
-        }
-
-        public void addButton(String button, CharSequence label) {
-            mButtons.add(button);
-            mLabels.add(label);
-            notifyItemInserted(mLabels.size() - 1);
-            notifyChanged();
-        }
-
-        public boolean hasHomeButton() {
-            final int N = mButtons.size();
-            for (int i = 0; i < N; i++) {
-                if (mButtons.get(i).startsWith(HOME)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        public String getNavString() {
-            StringBuilder builder = new StringBuilder();
-            for (int i = 1; i < mButtons.size() - 1; i++) {
-                String button = mButtons.get(i);
-                if (button.equals(CENTER) || button.equals(END)) {
-                    if (builder.length() == 0 || builder.toString().endsWith(GRAVITY_SEPARATOR)) {
-                        // No start or center buttons, fill with a space.
-                        builder.append(NAVSPACE);
-                    }
-                    builder.append(GRAVITY_SEPARATOR);
-                    continue;
-                } else if (builder.length() != 0 && !builder.toString().endsWith(
-                        GRAVITY_SEPARATOR)) {
-                    builder.append(BUTTON_SEPARATOR);
-                }
-                builder.append(button);
-            }
-            if (builder.toString().endsWith(GRAVITY_SEPARATOR)) {
-                // No end buttons, fill with space.
-                builder.append(NAVSPACE);
-            }
-            return builder.toString();
-        }
-
-        @Override
-        public int getItemViewType(int position) {
-            String button = mButtons.get(position);
-            if (button.equals(START) || button.equals(CENTER) || button.equals(END)) {
-                return CATEGORY_ID;
-            }
-            if (button.equals(ADD)) {
-                return ADD_ID;
-            }
-            return BUTTON_ID;
-        }
-
-        @Override
-        public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
-            final Context context = parent.getContext();
-            final LayoutInflater inflater = LayoutInflater.from(context);
-            final View view = inflater.inflate(getLayoutId(viewType), parent, false);
-            if (viewType == BUTTON_ID) {
-                inflater.inflate(R.layout.nav_control_widget,
-                        (ViewGroup) view.findViewById(android.R.id.widget_frame));
-            }
-            return new Holder(view);
-        }
-
-        private int getLayoutId(int viewType) {
-            if (viewType == CATEGORY_ID) {
-                return mCategoryLayout;
-            }
-            return mButtonLayout;
-        }
-
-        @Override
-        public void onBindViewHolder(Holder holder, int position) {
-            holder.title.setText(mLabels.get(position));
-            if (holder.getItemViewType() == BUTTON_ID) {
-                bindButton(holder, position);
-            } else if (holder.getItemViewType() == ADD_ID) {
-                bindAdd(holder);
-            }
-        }
-
-        private void bindAdd(Holder holder) {
-            TypedValue value = new TypedValue();
-            final Context context = holder.itemView.getContext();
-            context.getTheme().resolveAttribute(android.R.attr.colorAccent, value, true);
-            final ImageView icon = (ImageView) holder.itemView.findViewById(android.R.id.icon);
-            icon.setImageResource(R.drawable.ic_add);
-            icon.setImageTintList(ColorStateList.valueOf(context.getColor(value.resourceId)));
-            holder.itemView.findViewById(android.R.id.summary).setVisibility(View.GONE);
-            holder.itemView.setClickable(true);
-            holder.itemView.setOnClickListener(new View.OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    showAddDialog(v.getContext());
-                }
+        }), setting);
+        OnPreferenceChangeListener listener = (preference, newValue) -> {
+            mHandler.post(() -> {
+                setValue(setting, type, keycode, icon);
+                updateSummary(icon);
             });
-        }
-
-        private void bindButton(final Holder holder, int position) {
-            holder.itemView.findViewById(android.R.id.icon_frame).setVisibility(View.GONE);
-            holder.itemView.findViewById(android.R.id.summary).setVisibility(View.GONE);
-            bindClick(holder.itemView.findViewById(R.id.close), holder);
-            bindClick(holder.itemView.findViewById(R.id.width), holder);
-            holder.itemView.findViewById(R.id.drag).setOnTouchListener(new View.OnTouchListener() {
-                @Override
-                public boolean onTouch(View v, MotionEvent event) {
-                    mTouchHelper.startDrag(holder);
-                    return true;
-                }
-            });
-        }
-
-        private void showAddDialog(final Context context) {
-            final String[] options = new String[] {
-                    BACK, HOME, RECENT, MENU_IME, NAVSPACE, CLIPBOARD, KEY,
-            };
-            final CharSequence[] labels = new CharSequence[options.length];
-            for (int i = 0; i < options.length; i++) {
-                labels[i] = getLabel(options[i], context);
-            }
-            new AlertDialog.Builder(context)
-                    .setTitle(R.string.select_button)
-                    .setItems(labels, new DialogInterface.OnClickListener() {
-                        @Override
-                        public void onClick(DialogInterface dialog, int which) {
-                            if (KEY.equals(options[which])) {
-                                showKeyDialogs(context);
-                            } else {
-                                int index = mButtons.size() - 1;
-                                showAddedMessage(context, options[which]);
-                                mButtons.add(index, options[which]);
-                                mLabels.add(index, labels[which]);
-
-                                notifyItemInserted(index);
-                                notifyChanged();
-                            }
-                        }
-                    }).setNegativeButton(android.R.string.cancel, null)
-                    .show();
-        }
-
-        private void onImageSelected(Uri uri) {
-            int index = mButtons.size() - 1;
-            mButtons.add(index, KEY + KEY_CODE_START + mKeycode + KEY_IMAGE_DELIM + uri.toString()
-                    + KEY_CODE_END);
-            mLabels.add(index, getLabel(KEY, getContext()));
-
-            notifyItemInserted(index);
-            notifyChanged();
-        }
-
-        private void showKeyDialogs(final Context context) {
-            final KeycodeSelectionHelper.OnSelectionComplete listener =
-                    new KeycodeSelectionHelper.OnSelectionComplete() {
-                        @Override
-                        public void onSelectionComplete(int code) {
-                            mKeycode = code;
-                            selectImage();
-                        }
-                    };
-            new AlertDialog.Builder(context)
-                    .setTitle(R.string.keycode)
-                    .setMessage(R.string.keycode_description)
-                    .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
-                        @Override
-                        public void onClick(DialogInterface dialog, int which) {
-                            KeycodeSelectionHelper.showKeycodeSelect(context, listener);
-                        }
-                    }).show();
-        }
-
-        private void showAddedMessage(Context context, String button) {
-            if (CLIPBOARD.equals(button)) {
-                new AlertDialog.Builder(context)
-                        .setTitle(R.string.clipboard)
-                        .setMessage(R.string.clipboard_description)
-                        .setPositiveButton(android.R.string.ok, null)
-                        .show();
-            }
-        }
-
-        private void bindClick(View view, Holder holder) {
-            view.setOnClickListener(this);
-            view.setTag(holder);
-        }
-
-        @Override
-        public void onClick(View v) {
-            Holder holder = (Holder) v.getTag();
-            if (v.getId() == R.id.width) {
-                showWidthDialog(holder, v.getContext());
-            } else if (v.getId() == R.id.close) {
-                int position = holder.getAdapterPosition();
-                mButtons.remove(position);
-                mLabels.remove(position);
-                notifyItemRemoved(position);
-                notifyChanged();
-            }
-        }
-
-        private void showWidthDialog(final Holder holder, Context context) {
-            final String buttonSpec = mButtons.get(holder.getAdapterPosition());
-            float amount = extractSize(buttonSpec);
-            final AlertDialog dialog = new AlertDialog.Builder(context)
-                    .setTitle(R.string.adjust_button_width)
-                    .setView(R.layout.nav_width_view)
-                    .setNegativeButton(android.R.string.cancel, null).create();
-            dialog.setButton(DialogInterface.BUTTON_POSITIVE,
-                    context.getString(android.R.string.ok),
-                    new DialogInterface.OnClickListener() {
-                        @Override
-                        public void onClick(DialogInterface d, int which) {
-                            final String button = extractButton(buttonSpec);
-                            SeekBar seekBar = (SeekBar) dialog.findViewById(R.id.seekbar);
-                            if (seekBar.getProgress() == 75) {
-                                mButtons.set(holder.getAdapterPosition(), button);
-                            } else {
-                                float amount = (seekBar.getProgress() + 25) / 100f;
-                                mButtons.set(holder.getAdapterPosition(), button
-                                        + SIZE_MOD_START + amount + SIZE_MOD_END);
-                            }
-                            notifyChanged();
-                        }
-                    });
-            dialog.show();
-            SeekBar seekBar = (SeekBar) dialog.findViewById(R.id.seekbar);
-            // Range is .25 - 1.75.
-            seekBar.setMax(150);
-            seekBar.setProgress((int) ((amount - .25f) * 100));
-        }
-
-        @Override
-        public int getItemCount() {
-            return mButtons.size();
-        }
-
-        private final ItemTouchHelper.Callback mCallbacks = new ItemTouchHelper.Callback() {
-            @Override
-            public boolean isLongPressDragEnabled() {
-                return false;
-            }
-
-            @Override
-            public boolean isItemViewSwipeEnabled() {
-                return false;
-            }
-
-            @Override
-            public int getMovementFlags(RecyclerView recyclerView,
-                    RecyclerView.ViewHolder viewHolder) {
-                if (viewHolder.getItemViewType() != BUTTON_ID) {
-                    return makeMovementFlags(0, 0);
-                }
-                int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
-                return makeMovementFlags(dragFlags, 0);
-            }
-
-            @Override
-            public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
-                    RecyclerView.ViewHolder target) {
-                int from = viewHolder.getAdapterPosition();
-                int to = target.getAdapterPosition();
-                if (to == 0) {
-                    // Can't go above the top.
-                    return false;
-                }
-                move(from, to, mButtons);
-                move(from, to, mLabels);
-                notifyChanged();
-                notifyItemMoved(from, to);
-                return true;
-            }
-
-            private <T> void move(int from, int to, List<T> list) {
-                list.add(from > to ? to : to + 1, list.get(from));
-                list.remove(from > to ? from + 1 : from);
-            }
-
-            @Override
-            public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
-                // Don't care.
-            }
+            return true;
         };
+        type.setOnPreferenceChangeListener(listener);
+        icon.setOnPreferenceChangeListener(listener);
+        keycode.setOnPreferenceClickListener(preference -> {
+            EditText editText = new EditText(getContext());
+            new AlertDialog.Builder(getContext())
+                    .setTitle(preference.getTitle())
+                    .setView(editText)
+                    .setNegativeButton(android.R.string.cancel, null)
+                    .setPositiveButton(android.R.string.ok, (dialog, which) -> {
+                        int code = KeyEvent.KEYCODE_ENTER;
+                        try {
+                            code = Integer.parseInt(editText.getText().toString());
+                        } catch (Exception e) {
+                        }
+                        keycode.setSummary(code + "");
+                        setValue(setting, type, keycode, icon);
+                    }).show();
+            return true;
+        });
+    }
+
+    private void updateSummary(ListPreference icon) {
+        try {
+            int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14,
+                    getContext().getResources().getDisplayMetrics());
+            String pkg = icon.getValue().split("/")[0];
+            int id = Integer.parseInt(icon.getValue().split("/")[1]);
+            SpannableStringBuilder builder = new SpannableStringBuilder();
+            Drawable d = Icon.createWithResource(pkg, id)
+                    .loadDrawable(getContext());
+            d.setTint(Color.BLACK);
+            d.setBounds(0, 0, size, size);
+            ImageSpan span = new ImageSpan(d);
+            builder.append("  ", span, 0);
+            icon.setSummary(builder);
+        } catch (Exception e) {
+            Log.d("NavButton", "Problem with summary", e);
+            icon.setSummary(null);
+        }
+    }
+
+    private void setValue(String setting, DropDownPreference type, Preference keycode,
+            ListPreference icon) {
+        String button = type.getValue();
+        if (KEY.equals(button)) {
+            String uri = icon.getValue();
+            int code = KeyEvent.KEYCODE_ENTER;
+            try {
+                code = Integer.parseInt(keycode.getSummary().toString());
+            } catch (Exception e) {
+            }
+            button = button + KEY_CODE_START + code + KEY_IMAGE_DELIM + uri + KEY_CODE_END;
+        }
+        TunerService.get(getContext()).setValue(setting, button);
+    }
+
+    private void setupIcons(ListPreference icon) {
+        CharSequence[] labels = new CharSequence[ICONS.length];
+        CharSequence[] values = new CharSequence[ICONS.length];
+        int size = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14,
+                getContext().getResources().getDisplayMetrics());
+        for (int i = 0; i < ICONS.length; i++) {
+            SpannableStringBuilder builder = new SpannableStringBuilder();
+            Drawable d = Icon.createWithResource(getContext().getPackageName(), ICONS[i])
+                    .loadDrawable(getContext());
+            d.setTint(Color.BLACK);
+            d.setBounds(0, 0, size, size);
+            ImageSpan span = new ImageSpan(d);
+            builder.append("  ", span, 0);
+            labels[i] = builder;
+            values[i] = getContext().getPackageName() + "/" + ICONS[i];
+        }
+        icon.setEntries(labels);
+        icon.setEntryValues(values);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ShortcutParser.java b/packages/SystemUI/src/com/android/systemui/tuner/ShortcutParser.java
new file mode 100644
index 0000000..2aa51b3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/ShortcutParser.java
@@ -0,0 +1,162 @@
+/*
+ * 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.tuner;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.graphics.drawable.Icon;
+import android.util.AttributeSet;
+import android.util.Xml;
+
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ShortcutParser {
+    private static final String SHORTCUTS = "android.app.shortcuts";
+    private static final String SHORTCUT = "shortcut";
+    private static final String INTENT = "intent";
+
+    private final Context mContext;
+    private final String mPkg;
+    private final int mResId;
+    private final String mName;
+    private Resources mResources;
+    private AttributeSet mAttrs;
+
+    public ShortcutParser(Context context, ComponentName component) throws NameNotFoundException {
+        this(context, component.getPackageName(), component.getClassName(),
+                getResId(context, component));
+    }
+
+    private static int getResId(Context context, ComponentName component)
+            throws NameNotFoundException {
+        ActivityInfo i = context.getPackageManager().getActivityInfo(
+                component, PackageManager.GET_META_DATA);
+        int resId = 0;
+        if (i.metaData != null && i.metaData.containsKey(SHORTCUTS)) {
+            resId = i.metaData.getInt(SHORTCUTS);
+        }
+        return resId;
+    }
+
+    public ShortcutParser(Context context, String pkg, String name, int resId) {
+        mContext = context;
+        mPkg = pkg;
+        mResId = resId;
+        mName = name;
+    }
+
+    public List<Shortcut> getShortcuts() {
+        List<Shortcut> list = new ArrayList<>();
+        if (mResId != 0) {
+            try {
+                mResources = mContext.getPackageManager().getResourcesForApplication(mPkg);
+                XmlResourceParser parser = mResources.getXml(mResId);
+                mAttrs = Xml.asAttributeSet(parser);
+                int type;
+                while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+                    if (type != XmlPullParser.START_TAG) {
+                        continue;
+                    }
+                    if (parser.getName().equals(SHORTCUT)) {
+                        Shortcut c = parseShortcut(parser);
+                        if (c != null) {
+                            list.add(c);
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        return list;
+    }
+
+    private Shortcut parseShortcut(XmlResourceParser parser)
+            throws IOException, XmlPullParserException {
+        final TypedArray sa = mResources.obtainAttributes(mAttrs, R.styleable.Shortcut);
+        Shortcut c = new Shortcut();
+
+        final boolean enabled = sa.getBoolean(R.styleable.Shortcut_enabled, true);
+        if (!enabled) return null;
+        final String id = sa.getString(R.styleable.Shortcut_shortcutId);
+        final int iconResId = sa.getResourceId(R.styleable.Shortcut_icon, 0);
+        final int titleResId = sa.getResourceId(R.styleable.Shortcut_shortcutShortLabel, 0);
+
+        c.pkg = mPkg;
+        c.icon = Icon.createWithResource(mPkg, iconResId);
+        c.id = id;
+        c.label = mResources.getString(titleResId);
+        c.name = mName;
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_TAG) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+            if (parser.getName().equals(INTENT)) {
+                c.intent = Intent.parseIntent(mResources, parser, mAttrs);
+            }
+        }
+        return c.intent != null ? c : null;
+    }
+
+    public static class Shortcut {
+        public Intent intent;
+        public String label;
+        public Icon icon;
+        public String pkg;
+        public String id;
+        public String name;
+
+        public static Shortcut create(Context context, String value) {
+            String[] sp = value.split("::");
+            try {
+                for (Shortcut shortcut : new ShortcutParser(context,
+                        new ComponentName(sp[0], sp[1])).getShortcuts()) {
+                    if (shortcut.id.equals(sp[2])) {
+                        return shortcut;
+                    }
+                }
+            } catch (NameNotFoundException e) {
+            }
+            return null;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append(pkg);
+            builder.append("::");
+            builder.append(name);
+            builder.append("::");
+            builder.append(id);
+            return builder.toString();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index 565ac08..fb94061 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -33,6 +33,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.provider.Settings.Secure;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -126,6 +127,12 @@
         return Settings.Secure.getIntForUser(mContentResolver, setting, def, mCurrentUser);
     }
 
+    public String getValue(String setting, String def) {
+        String ret = Secure.getStringForUser(mContentResolver, setting, mCurrentUser);
+        if (ret == null) return def;
+        return ret;
+    }
+
     public void setValue(String setting, int value) {
          Settings.Secure.putIntForUser(mContentResolver, setting, value, mCurrentUser);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 2c90e62..9a16d6d 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -43,6 +43,7 @@
 import com.android.internal.R;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.systemui.SystemUI;
+import com.android.systemui.util.NotificationChannels;
 
 import java.util.List;
 
@@ -206,6 +207,7 @@
                         .setStyle(new Notification.BigTextStyle().bigText(text))
                         .setVisibility(Notification.VISIBILITY_PUBLIC)
                         .setLocalOnly(true)
+                        .setChannel(NotificationChannels.STORAGE)
                         .setCategory(Notification.CATEGORY_SYSTEM)
                         .setDeleteIntent(buildSnoozeIntent(fsUuid));
                 SystemUI.overrideNotificationAppName(mContext, builder);
@@ -225,6 +227,7 @@
                     R.string.ext_media_unsupported_notification_message, disk.getDescription());
 
             Notification.Builder builder = new Notification.Builder(mContext)
+                    .setChannel(NotificationChannels.STORAGE)
                     .setSmallIcon(getSmallIcon(disk, VolumeInfo.STATE_UNMOUNTABLE))
                     .setColor(mContext.getColor(R.color.system_notification_accent_color))
                     .setContentTitle(title)
@@ -331,7 +334,6 @@
 
         return buildNotificationBuilder(vol, title, text)
                 .setCategory(Notification.CATEGORY_PROGRESS)
-                .setPriority(Notification.PRIORITY_LOW)
                 .setOngoing(true)
                 .build();
     }
@@ -360,7 +362,6 @@
                             buildUnmountPendingIntent(vol)))
                     .setContentIntent(initIntent)
                     .setDeleteIntent(buildSnoozeIntent(vol.getFsUuid()))
-                    .setCategory(Notification.CATEGORY_SYSTEM)
                     .build();
 
         } else {
@@ -377,8 +378,7 @@
                             mContext.getString(R.string.ext_media_unmount_action),
                             buildUnmountPendingIntent(vol)))
                     .setContentIntent(browseIntent)
-                    .setCategory(Notification.CATEGORY_SYSTEM)
-                    .setPriority(Notification.PRIORITY_LOW);
+                    .setCategory(Notification.CATEGORY_SYSTEM);
             // Non-adoptable disks can't be snoozed.
             if (disk.isAdoptable()) {
                 builder.setDeleteIntent(buildSnoozeIntent(vol.getFsUuid()));
@@ -402,7 +402,6 @@
 
         return buildNotificationBuilder(vol, title, text)
                 .setCategory(Notification.CATEGORY_PROGRESS)
-                .setPriority(Notification.PRIORITY_LOW)
                 .setOngoing(true)
                 .build();
     }
@@ -485,8 +484,8 @@
                 .setStyle(new Notification.BigTextStyle().bigText(text))
                 .setVisibility(Notification.VISIBILITY_PUBLIC)
                 .setLocalOnly(true)
+                .setChannel(NotificationChannels.STORAGE)
                 .setCategory(Notification.CATEGORY_PROGRESS)
-                .setPriority(Notification.PRIORITY_LOW)
                 .setProgress(100, status, false)
                 .setOngoing(true);
         SystemUI.overrideNotificationAppName(mContext, builder);
@@ -537,7 +536,7 @@
                 .setVisibility(Notification.VISIBILITY_PUBLIC)
                 .setLocalOnly(true)
                 .setCategory(Notification.CATEGORY_SYSTEM)
-                .setPriority(Notification.PRIORITY_LOW)
+                .setChannel(NotificationChannels.STORAGE)
                 .setAutoCancel(true);
         SystemUI.overrideNotificationAppName(mContext, builder);
 
@@ -564,6 +563,7 @@
     private Notification.Builder buildNotificationBuilder(VolumeInfo vol, CharSequence title,
             CharSequence text) {
         Notification.Builder builder = new Notification.Builder(mContext)
+                .setChannel(NotificationChannels.STORAGE)
                 .setSmallIcon(getSmallIcon(vol.getDisk(), vol.getState()))
                 .setColor(mContext.getColor(R.color.system_notification_accent_color))
                 .setContentTitle(title)
diff --git a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
new file mode 100644
index 0000000..6bb8aea
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
@@ -0,0 +1,65 @@
+/*
+ * 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.util;
+
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+
+import android.content.Context;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.R;
+import com.android.systemui.SystemUI;
+
+import java.util.Arrays;
+
+public class NotificationChannels extends SystemUI {
+    public static String ALERTS      = "ALR";
+    public static String SCREENSHOTS = "SCN";
+    public static String SECURITY    = "SEC";
+    public static String USER        = "USR";
+    public static String STORAGE     = "DSK";
+
+    @VisibleForTesting
+    static void createAll(Context context) {
+        final NotificationManager nm = context.getSystemService(NotificationManager.class);
+        nm.createNotificationChannels(Arrays.asList(
+                new NotificationChannel(
+                        ALERTS,
+                        context.getString(R.string.notification_channel_alerts),
+                        NotificationManager.IMPORTANCE_HIGH),
+                new NotificationChannel(
+                        SCREENSHOTS,
+                        context.getString(R.string.notification_channel_screenshot),
+                        NotificationManager.IMPORTANCE_DEFAULT),
+                new NotificationChannel(
+                        SECURITY,
+                        context.getString(R.string.notification_channel_security),
+                        NotificationManager.IMPORTANCE_HIGH),
+                new NotificationChannel(
+                        USER,
+                        context.getString(R.string.notification_channel_user_status),
+                        NotificationManager.IMPORTANCE_MIN),
+                new NotificationChannel(
+                        STORAGE,
+                        context.getString(R.string.notification_channel_storage),
+                        NotificationManager.IMPORTANCE_LOW)
+                ));
+    }
+
+    @Override
+    public void start() {
+        createAll(mContext);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index 137a12f..78145fe 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -31,7 +31,6 @@
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.qs.tiles.DndTile;
-import com.android.systemui.statusbar.phone.PhoneStatusBar;
 import com.android.systemui.statusbar.policy.ZenModeController;
 import com.android.systemui.tuner.TunerService;
 
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index 90e9321..408e8f3 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -33,6 +33,7 @@
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
     <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
+    <uses-permission android:name="android.permission.REQUEST_NETWORK_SCORES" />
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsTest.java
index cac0806..166fcb1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsTest.java
@@ -63,7 +63,7 @@
     private static final String TEST_CHANNEL = "test_channel";
     private static final String TEST_CHANNEL_NAME = "TEST CHANNEL NAME";
 
-    private NotificationGuts mNotificationGuts;
+    private NotificationInfo mNotificationInfo;
     private final INotificationManager mMockINotificationManager = mock(INotificationManager.class);
     private final PackageManager mMockPackageManager = mock(PackageManager.class);
     private NotificationChannel mNotificationChannel;
@@ -76,7 +76,7 @@
         // Inflate the layout
         final LayoutInflater layoutInflater =
                 LayoutInflater.from(InstrumentationRegistry.getTargetContext());
-        mNotificationGuts = (NotificationGuts) layoutInflater.inflate(R.layout.notification_guts,
+        mNotificationInfo = (NotificationInfo) layoutInflater.inflate(R.layout.notification_info,
                 null);
 
         // PackageManager must return a packageInfo and applicationInfo.
@@ -98,18 +98,18 @@
     @UiThreadTest
     public void testBindNotification_SetsTextApplicationName() throws Exception {
         when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
-        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
-        final TextView textView = (TextView) mNotificationGuts.findViewById(R.id.pkgname);
+        final TextView textView = (TextView) mNotificationInfo.findViewById(R.id.pkgname);
         assertTrue(textView.getText().toString().contains("App Name"));
     }
 
     @Test
     @UiThreadTest
     public void testBindNotification_SetsTextChannelName() throws Exception {
-        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
-        final TextView textView = (TextView) mNotificationGuts.findViewById(R.id.channel_name);
+        final TextView textView = (TextView) mNotificationInfo.findViewById(R.id.channel_name);
         assertEquals(TEST_CHANNEL_NAME, textView.getText());
     }
 
@@ -117,12 +117,12 @@
     @UiThreadTest
     public void testBindNotification_SetsOnClickListenerForSettings() throws Exception {
         final CountDownLatch latch = new CountDownLatch(1);
-        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel,
                 (View v, int appUid) -> { latch.countDown(); }, null, null);
 
-        final TextView settingsButton =
-                (TextView) mNotificationGuts.findViewById(R.id.more_settings);
+        final TextView settingsButton = 
+                (TextView) mNotificationInfo.findViewById(R.id.more_settings);
         settingsButton.performClick();
         // Verify that listener was triggered.
         assertEquals(0, latch.getCount());
@@ -132,12 +132,12 @@
     @UiThreadTest
     public void testBindNotification_SetsOnClickListenerForDone() throws Exception {
         final CountDownLatch latch = new CountDownLatch(1);
-        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null,
                 (View v) -> { latch.countDown(); },
                 null);
 
-        final TextView doneButton = (TextView) mNotificationGuts.findViewById(R.id.done);
+        final TextView doneButton = (TextView) mNotificationInfo.findViewById(R.id.done);
         doneButton.performClick();
         // Verify that listener was triggered.
         assertEquals(0, latch.getCount());
@@ -146,38 +146,38 @@
     @Test
     @UiThreadTest
     public void testHasImportanceChanged_DefaultsToFalse() throws Exception {
-        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
-        assertFalse(mNotificationGuts.hasImportanceChanged());
+        assertFalse(mNotificationInfo.hasImportanceChanged());
     }
 
     @Test
     @UiThreadTest
     public void testHasImportanceChanged_ReturnsTrueAfterButtonChecked() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
-        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
         // Find the high button and check it.
-        RadioButton highButton = (RadioButton) mNotificationGuts.findViewById(R.id.high_importance);
+        RadioButton highButton = (RadioButton) mNotificationInfo.findViewById(R.id.high_importance);
         highButton.setChecked(true);
-        assertTrue(mNotificationGuts.hasImportanceChanged());
+        assertTrue(mNotificationInfo.hasImportanceChanged());
     }
 
     @Test
     @UiThreadTest
     public void testImportanceButtonCheckedBasedOnInitialImportance() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_HIGH);
-        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
 
-        RadioButton highButton = (RadioButton) mNotificationGuts.findViewById(R.id.high_importance);
+        RadioButton highButton = (RadioButton) mNotificationInfo.findViewById(R.id.high_importance);
         assertTrue(highButton.isChecked());
     }
 
     @Test
     @UiThreadTest
     public void testBindNotification_DoesNotUpdateNotificationChannel() throws Exception {
-        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
         verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
                 anyString(), anyInt(), any());
@@ -187,10 +187,10 @@
     @UiThreadTest
     public void testDoesNotUpdateNotificationChannelAfterImportanceChanged() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
-        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
 
-        RadioButton highButton = (RadioButton) mNotificationGuts.findViewById(R.id.high_importance);
+        RadioButton highButton = (RadioButton) mNotificationInfo.findViewById(R.id.high_importance);
         highButton.setChecked(true);
         verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
                 anyString(), anyInt(), any());
@@ -199,10 +199,10 @@
     @Test
     @UiThreadTest
     public void testCloseControls_DoesNotUpdateNotificationChannelIfUnchanged() throws Exception {
-        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
 
-        mNotificationGuts.closeControls(-1, -1, true);
+        mNotificationInfo.closeControls();
         verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
                 anyString(), anyInt(), any());
     }
@@ -211,10 +211,10 @@
     @UiThreadTest
     public void testCloseControls_DoesNotUpdateNotificationChannelIfUnspecified() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_UNSPECIFIED);
-        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
 
-        mNotificationGuts.closeControls(-1, -1, true);
+        mNotificationInfo.closeControls();
         verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
                 anyString(), anyInt(), any());
     }
@@ -223,12 +223,12 @@
     @UiThreadTest
     public void testCloseControls_CallsUpdateNotificationChannelIfChanged() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
-        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
 
-        RadioButton highButton = (RadioButton) mNotificationGuts.findViewById(R.id.high_importance);
+        RadioButton highButton = (RadioButton) mNotificationInfo.findViewById(R.id.high_importance);
         highButton.setChecked(true);
-        mNotificationGuts.closeControls(-1, -1, true);
+        mNotificationInfo.closeControls();
         verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
                 eq(TEST_PACKAGE_NAME), anyInt(), eq(mNotificationChannel));
         assertEquals(NotificationManager.IMPORTANCE_HIGH, mNotificationChannel.getImportance());
@@ -238,12 +238,12 @@
     @UiThreadTest
     public void testCloseControls_DoesNotUpdateNotificationChannelIfSaveFalse() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
-        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
 
-        RadioButton highButton = (RadioButton) mNotificationGuts.findViewById(R.id.high_importance);
+        RadioButton highButton = (RadioButton) mNotificationInfo.findViewById(R.id.high_importance);
         highButton.setChecked(true);
-        mNotificationGuts.closeControls(-1, -1, false);
+        mNotificationInfo.closeControls();
         verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
                 anyString(), anyInt(), any());
     }
@@ -252,10 +252,10 @@
     @UiThreadTest
     public void testEnabledSwitchOnByDefault() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
-        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
 
-        Switch enabledSwitch = (Switch) mNotificationGuts.findViewById(R.id.channel_enabled_switch);
+        Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
         assertTrue(enabledSwitch.isChecked());
     }
 
@@ -263,10 +263,10 @@
     @UiThreadTest
     public void testEnabledSwitchVisibleByDefault() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
-        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
 
-        Switch enabledSwitch = (Switch) mNotificationGuts.findViewById(R.id.channel_enabled_switch);
+        Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
         assertEquals(View.VISIBLE, enabledSwitch.getVisibility());
     }
 
@@ -274,11 +274,11 @@
     @UiThreadTest
     public void testEnabledSwitchInvisibleIfNonBlockable() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
-        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null,
                 Collections.singleton(TEST_PACKAGE_NAME));
 
-        Switch enabledSwitch = (Switch) mNotificationGuts.findViewById(R.id.channel_enabled_switch);
+        Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
         assertEquals(View.INVISIBLE, enabledSwitch.getVisibility());
     }
 
@@ -286,13 +286,13 @@
     @UiThreadTest
     public void testEnabledSwitchChangedCallsUpdateNotificationChannel() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
-        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null,
                 Collections.singleton(TEST_PACKAGE_NAME));
 
-        Switch enabledSwitch = (Switch) mNotificationGuts.findViewById(R.id.channel_enabled_switch);
+        Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
         enabledSwitch.setChecked(false);
-        mNotificationGuts.closeControls(-1, -1, true);
+        mNotificationInfo.closeControls();
         verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
                 eq(TEST_PACKAGE_NAME), anyInt(), eq(mNotificationChannel));
     }
@@ -301,14 +301,14 @@
     @UiThreadTest
     public void testEnabledSwitchOverridesOtherButtons() throws Exception {
         mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
-        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 mMockStatusBarNotification, mNotificationChannel, null, null, null);
 
-        Switch enabledSwitch = (Switch) mNotificationGuts.findViewById(R.id.channel_enabled_switch);
-        RadioButton lowButton = (RadioButton) mNotificationGuts.findViewById(R.id.low_importance);
+        Switch enabledSwitch = (Switch) mNotificationInfo.findViewById(R.id.channel_enabled_switch);
+        RadioButton lowButton = (RadioButton) mNotificationInfo.findViewById(R.id.low_importance);
         lowButton.setChecked(true);
         enabledSwitch.setChecked(false);
-        mNotificationGuts.closeControls(-1, -1, true);
+        mNotificationInfo.closeControls();
         assertEquals(NotificationManager.IMPORTANCE_NONE, mNotificationChannel.getImportance());
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
index 525a361..e28d077 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
@@ -20,7 +20,6 @@
 import android.view.WindowManager;
 
 import com.android.systemui.FragmentTestCase;
-import com.android.systemui.assist.AssistManager;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.CommandQueue;
@@ -37,7 +36,7 @@
     @Before
     public void setup() {
         mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
-        mContext.putComponent(PhoneStatusBar.class, mock(PhoneStatusBar.class));
+        mContext.putComponent(StatusBar.class, mock(StatusBar.class));
         mContext.putComponent(Recents.class, mock(Recents.class));
         mContext.putComponent(Divider.class, mock(Divider.class));
         mContext.addMockSystemService(Context.WINDOW_SERVICE, mock(WindowManager.class));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
similarity index 80%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index d82566f..309559b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -27,7 +27,6 @@
 
 import com.android.keyguard.KeyguardHostView.OnDismissAction;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.BaseStatusBar;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -35,15 +34,15 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class PhoneStatusBarTest extends SysuiTestCase {
+public class StatusBarTest extends SysuiTestCase {
 
     StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
-    PhoneStatusBar mPhoneStatusBar;
+    StatusBar mStatusBar;
 
     @Before
     public void setup() {
         mStatusBarKeyguardViewManager = mock(StatusBarKeyguardViewManager.class);
-        mPhoneStatusBar = new TestablePhoneStatusBar(mStatusBarKeyguardViewManager);
+        mStatusBar = new TestableStatusBar(mStatusBarKeyguardViewManager);
 
         doAnswer(invocation -> {
             OnDismissAction onDismissAction = (OnDismissAction) invocation.getArguments()[0];
@@ -63,7 +62,7 @@
         when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
         when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(true);
 
-        mPhoneStatusBar.executeRunnableDismissingKeyguard(null, null, false, false, false);
+        mStatusBar.executeRunnableDismissingKeyguard(null, null, false, false, false);
     }
 
     @Test
@@ -71,7 +70,7 @@
         when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
         when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
 
-        mPhoneStatusBar.executeRunnableDismissingKeyguard(null, null, false, false, false);
+        mStatusBar.executeRunnableDismissingKeyguard(null, null, false, false, false);
     }
 
     @Test
@@ -79,16 +78,16 @@
         when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(false);
         when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
 
-        mPhoneStatusBar.executeRunnableDismissingKeyguard(null, null, false, false, false);
+        mStatusBar.executeRunnableDismissingKeyguard(null, null, false, false, false);
     }
 
-    static class TestablePhoneStatusBar extends PhoneStatusBar {
-        public TestablePhoneStatusBar(StatusBarKeyguardViewManager man) {
+    static class TestableStatusBar extends StatusBar {
+        public TestableStatusBar(StatusBarKeyguardViewManager man) {
             mStatusBarKeyguardViewManager = man;
         }
 
         @Override
-        protected BaseStatusBar.H createHandler() {
+        protected H createHandler() {
             return null;
         }
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
index c969cc2..b544d9d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
@@ -36,6 +36,8 @@
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.Assert.assertEquals;
 
+import static org.mockito.Matchers.eq;
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class CallbackHandlerTest {
@@ -109,8 +111,9 @@
         int qsType = R.drawable.ic_qs_signal_1x;
         boolean wide = true;
         int subId = 5;
+        boolean roaming = true;
         mHandler.setMobileDataIndicators(status, qs, type, qsType, in, out, typeDescription,
-                description, wide, subId);
+                description, wide, subId, roaming);
         waitForCallbacks();
 
         ArgumentCaptor<IconState> statusArg = ArgumentCaptor.forClass(IconState.class);
@@ -126,7 +129,7 @@
         Mockito.verify(mSignalCallback).setMobileDataIndicators(statusArg.capture(),
                 qsArg.capture(), typeIconArg.capture(), qsTypeIconArg.capture(), inArg.capture(),
                 outArg.capture(), typeContentArg.capture(), descArg.capture(), wideArg.capture(),
-                subIdArg.capture());
+                subIdArg.capture(), eq(roaming));
         assertEquals(status, statusArg.getValue());
         assertEquals(qs, qsArg.getValue());
         assertEquals(type, (int) typeIconArg.getValue());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 6aa021e..0e5f513 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -55,6 +55,7 @@
 import static org.mockito.Matchers.anyBoolean;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -297,7 +298,7 @@
                     iconArg.capture(),
                     anyInt(),
                     typeIconArg.capture(), dataInArg.capture(), dataOutArg.capture(),
-                    anyString(), anyString(), anyBoolean(), anyInt());
+                    anyString(), anyString(), anyBoolean(), anyInt(), anyBoolean());
         IconState iconState = iconArg.getValue();
         assertEquals("Visibility in, quick settings", visible, iconState.visible);
         assertEquals("Signal icon in, quick settings", icon, iconState.icon);
@@ -309,6 +310,11 @@
     }
 
     protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon) {
+        verifyLastMobileDataIndicators(visible, icon, typeIcon, false);
+    }
+
+    protected void verifyLastMobileDataIndicators(boolean visible, int icon, int typeIcon,
+            boolean roaming) {
         ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
         ArgumentCaptor<Integer> typeIconArg = ArgumentCaptor.forClass(Integer.class);
 
@@ -318,9 +324,10 @@
                 any(),
                 typeIconArg.capture(),
                 anyInt(), anyBoolean(), anyBoolean(), anyString(), anyString(), anyBoolean(),
-                anyInt());
+                anyInt(), eq(roaming));
         IconState iconState = iconArg.getValue();
 
+        assertEquals("Signal icon in status bar", icon, iconState.icon);
         assertEquals("Data icon in status bar", typeIcon, (int) typeIconArg.getValue());
         assertEquals("Visibility in status bar", visible, iconState.visible);
     }
@@ -341,7 +348,7 @@
                 qsTypeIconArg.capture(),
                 dataInArg.capture(),
                 dataOutArg.capture(),
-                anyString(), anyString(), anyBoolean(), anyInt());
+                anyString(), anyString(), anyBoolean(), anyInt(), anyBoolean());
 
         IconState iconState = iconArg.getValue();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index 1ec0418..d7f961c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -25,19 +25,6 @@
     }
 
     @Test
-    public void testRoamingDataIcon() {
-        setupDefaultSignal();
-        setGsmRoaming(true);
-
-        verifyLastMobileDataIndicators(true,
-                TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[1][DEFAULT_LEVEL],
-                TelephonyIcons.ROAMING_ICON,
-                true,
-                TelephonyIcons.QS_TELEPHONY_SIGNAL_STRENGTH[1][DEFAULT_LEVEL],
-                TelephonyIcons.QS_DATA_R, false, false);
-    }
-
-    @Test
     public void test2gDataIcon() {
         setupDefaultSignal();
         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index 00e5926..2c0f9c9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -158,13 +158,12 @@
         for (int testStrength = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
                 testStrength <= SignalStrength.SIGNAL_STRENGTH_GREAT; testStrength++) {
             setupDefaultSignal();
-            setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
             setGsmRoaming(true);
             setLevel(testStrength);
 
             verifyLastMobileDataIndicators(true,
                     TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[1][testStrength],
-                    TelephonyIcons.ROAMING_ICON);
+                    DEFAULT_ICON, true);
         }
     }
 
@@ -179,7 +178,7 @@
 
             verifyLastMobileDataIndicators(true,
                     TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[1][testStrength],
-                    TelephonyIcons.ROAMING_ICON);
+                    TelephonyIcons.DATA_1X[1][0 /* No direction */], true);
         }
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
index 06a5122..9b382f6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
@@ -1,7 +1,6 @@
 package com.android.systemui.statusbar.policy;
 
 import android.content.Intent;
-import android.graphics.drawable.Drawable;
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.NetworkKey;
@@ -30,7 +29,6 @@
 import org.mockito.stubbing.Answer;
 
 import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNotNull;
 
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyBoolean;
@@ -60,8 +58,6 @@
     private final List<NetworkKey> mRequestedKeys = new ArrayList<>();
     private CountDownLatch mRequestScoresLatch;
 
-    private SettingOverrider mSettingsOverrider;
-
     @Test
     public void testWifiIcon() {
         String testSsid = "Test SSID";
@@ -83,6 +79,7 @@
 
     @Test
     public void testBadgedWifiIcon() throws Exception {
+        // TODO(sghuman): Refactor this setup code when creating a test for the badged QsIcon.
         int testLevel = 1;
         RssiCurve mockBadgeCurve = mock(RssiCurve.class);
         Bundle attr = new Bundle();
@@ -94,12 +91,16 @@
                         false /* meteredHint */,
                         attr);
 
-        // Enable scoring
-        mSettingsOverrider = mContext.getSettingsProvider().acquireOverridesBuilder(this)
-                .addSetting("global", Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, "1")
-                .build();
-
+        // Must set the Settings value before instantiating the NetworkControllerImpl due to bugs in
+        // FakeSettingsProvider.
+        SettingOverrider settingsOverrider =
+                mContext.getSettingsProvider().acquireOverridesBuilder(this)
+                        .addSetting("global", Settings.Global.NETWORK_SCORING_UI_ENABLED, "1")
+                        .build();
+        super.setUp(); // re-instantiate NetworkControllImpl now that setting has been updated
         setupNetworkScoreManager();
+
+        // Test Requesting Scores
         mRequestScoresLatch = new CountDownLatch(1);
         setWifiEnabled(true);
         setWifiState(true, TEST_SSID, TEST_BSSID);
@@ -115,23 +116,23 @@
                 Matchers.anyInt());
         scoreCacheCaptor.getValue().updateScores(Arrays.asList(score));
 
+        //  Test badge is set
         setWifiLevel(testLevel);
-        NetworkController.SignalCallback mockCallback =
-                mock(NetworkController.SignalCallback.class);
-        mNetworkController.addCallback(mockCallback);
 
-        ArgumentCaptor<IconState> iconState = ArgumentCaptor.forClass(IconState.class);
-        Mockito.verify(mockCallback).setWifiIndicators(
-                anyBoolean(), iconState.capture(), any(), anyBoolean(), anyBoolean(), any());
+        ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class);
+        Mockito.verify(mCallbackHandler, Mockito.atLeastOnce()).setWifiIndicators(
+                anyBoolean(), iconArg.capture(), any(), anyBoolean(), anyBoolean(),
+                any());
+        IconState iconState = iconArg.getValue();
 
         assertEquals("Badged Wifi Resource is set",
                 Utils.WIFI_PIE_FOR_BADGING[testLevel],
-                iconState.getValue().icon);
+                iconState.icon);
         assertEquals("SD Badge is set",
                 Utils.getWifiBadgeResource(ScoredNetwork.BADGING_SD),
-                iconState.getValue().iconOverlay);
+                iconState.iconOverlay);
 
-        mSettingsOverrider.release();
+        settingsOverrider.release();
     }
 
     private void setupNetworkScoreManager() {
@@ -215,9 +216,10 @@
         setGsmRoaming(true);
         // Still be on wifi though.
         setConnectivity(NetworkCapabilities.TRANSPORT_WIFI, true, true);
+        setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
         verifyLastMobileDataIndicators(true,
                 TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH_ROAMING[1][DEFAULT_LEVEL],
-                TelephonyIcons.ROAMING_ICON);
+                0, true);
     }
 
     protected void setWifiActivity(int activity) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/ChannelsTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/ChannelsTest.java
new file mode 100644
index 0000000..8949598
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/ChannelsTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.ArraySet;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.util.NotificationChannels;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ChannelsTest extends SysuiTestCase {
+    private final NotificationManager mMockNotificationManager = mock(NotificationManager.class);
+
+    @Before
+    public void setup() throws Exception {
+        mContext.addMockSystemService(Context.NOTIFICATION_SERVICE, mMockNotificationManager);
+    }
+
+    @Test
+    public void testChannelSetup() {
+        Set<String> ALL_CHANNELS = new ArraySet<>(Arrays.asList(
+                NotificationChannels.ALERTS,
+                NotificationChannels.SCREENSHOTS,
+                NotificationChannels.SECURITY,
+                NotificationChannels.USER,
+                NotificationChannels.STORAGE
+        ));
+        NotificationChannels.createAll(mContext);
+        ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
+        verify(mMockNotificationManager).createNotificationChannels(captor.capture());
+        final List<NotificationChannel> list = captor.getValue();
+        assertEquals(ALL_CHANNELS.size(), list.size());
+        list.forEach((chan) -> assertTrue(ALL_CHANNELS.contains(chan.getId())));
+    }
+}
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index a474759..f906ee2 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -3276,8 +3276,8 @@
     DEFAULT_APP_PICKER_CONFIRMATION_DIALOG = 791;
 
 
-    // OPEN: Settings > Apps > Default Apps > Default auto-fill app
-    DEFAULT_AUTO_FILL_PICKER = 792;
+    // OPEN: Settings > Apps > Default Apps > Default autofill app
+    DEFAULT_AUTOFILL_PICKER = 792;
 
     // These values should never appear in log outputs - they are reserved for
     // internal Tron use.
@@ -3339,6 +3339,18 @@
     // ACTION: Settings -> Display -> Theme
     ACTION_THEME = 816;
 
+    // OPEN: SUW Welcome Screen -> Vision Settings -> Select to Speak
+    // ACTION: Select to Speak configuration is chosen
+    //  SUBTYPE: 0 is off, 1 is on
+    // CATEGORY: SETTINGS
+    // OS: N
+    SUW_ACCESSIBILITY_TOGGLE_SELECT_TO_SPEAK = 817;
+
+    // OPEN: Settings > System > Backup
+    // CATEGORY: SETTINGS
+    // OS: O
+    BACKUP_SETTINGS = 818;
+
     // ---- End O Constants, all O constants go above this line ----
 
     // Add new aosp constants above this line.
diff --git a/rs/java/android/renderscript/ScriptIntrinsicBLAS.java b/rs/java/android/renderscript/ScriptIntrinsicBLAS.java
index c04191b..49a71b4 100644
--- a/rs/java/android/renderscript/ScriptIntrinsicBLAS.java
+++ b/rs/java/android/renderscript/ScriptIntrinsicBLAS.java
@@ -2441,10 +2441,10 @@
      * @param TransA The type of transpose applied to matrix A.
      * @param TransB The type of transpose applied to matrix B.
      * @param alpha The scalar alpha.
-     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2
-     * @param B The input allocation contains matrix B, supported elements type {@link Element#F64_2
+     * @param A The input allocation contains matrix A, supported elements type {@link Element#F64_2}.
+     * @param B The input allocation contains matrix B, supported elements type {@link Element#F64_2}.
      * @param beta The scalar beta.
-     * @param C The input allocation contains matrix C, supported elements type {@link Element#F64_2
+     * @param C The input allocation contains matrix C, supported elements type {@link Element#F64_2}.
      */
     public void ZGEMM(@Transpose int TransA, @Transpose int TransB, Double2 alpha, Allocation A,
                       Allocation B, Double2 beta, Allocation C) {
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 3523706..ce50b30 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -42,6 +42,7 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
+import android.content.pm.LauncherApps;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -1547,6 +1548,13 @@
     }
 
     @Override
+    public boolean isRequestPinAppWidgetSupported() {
+        return LocalServices.getService(ShortcutServiceInternal.class)
+                .isRequestPinItemSupported(UserHandle.getCallingUserId(),
+                        LauncherApps.PinItemRequest.REQUEST_TYPE_APPWIDGET);
+    }
+
+    @Override
     public boolean requestPinAppWidget(String callingPackage, ComponentName componentName,
             IntentSender resultSender) {
         final int callingUid = Binder.getCallingUid();
diff --git a/services/autofill/java/com/android/server/autofill/AnchoredWindow.java b/services/autofill/java/com/android/server/autofill/AnchoredWindow.java
new file mode 100644
index 0000000..e674309
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/AnchoredWindow.java
@@ -0,0 +1,133 @@
+/*
+ * 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.server.autofill;
+
+import static com.android.server.autofill.Helper.DEBUG;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.Slog;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.widget.FrameLayout;
+
+/**
+ * A window above the application that is smartly anchored to a rectangular region.
+ */
+final class AnchoredWindow {
+    private static final String TAG = "AutoFill";
+
+    private final WindowManager mWm;
+    private final View mRootView;
+    private final View mView;
+    private final int mWidth;
+    private final int mHeight;
+    private boolean mIsShowing = false;
+
+    /**
+     * Constructor.
+     *
+     * @param wm window manager that draws the view on a window
+     * @param view singleton view in the window
+     * @param width requested width of the view
+     * @param height requested height of the view
+     */
+    AnchoredWindow(WindowManager wm, View view, int width, int height) {
+        mWm = wm;
+        mRootView = wrapView(view, width, height);
+        mView = view;
+        mWidth = width;
+        mHeight = height;
+    }
+
+    /**
+     * Shows the window.
+     *
+     * @param bounds the rectangular region this window should be anchored to
+     */
+    void show(Rect bounds) {
+        LayoutParams params = createBaseLayoutParams();
+        params.x = bounds.left;
+        params.y = bounds.bottom;
+
+        if (!mIsShowing) {
+            if (DEBUG) Slog.d(TAG, "adding view " + mView);
+            mWm.addView(mRootView, params);
+        } else {
+            if (DEBUG) Slog.d(TAG, "updating view " + mView);
+            mWm.updateViewLayout(mRootView, params);
+        }
+        mIsShowing = true;
+    }
+
+    /**
+     * Hides the window.
+     */
+    void hide() {
+        if (DEBUG) Slog.d(TAG, "removing view " + mView);
+        if (mIsShowing) {
+            mWm.removeView(mRootView);
+        }
+        mIsShowing = false;
+    }
+
+    /**
+     * Wraps a view with a SelfRemovingView and sets its requested width and height.
+     */
+    private View wrapView(View view, int width, int height) {
+        ViewGroup viewGroup = new SelfRemovingView(view.getContext());
+        viewGroup.addView(view, new ViewGroup.LayoutParams(width, height));
+        return viewGroup;
+    }
+
+    private static LayoutParams createBaseLayoutParams() {
+        LayoutParams params = new LayoutParams();
+        // TODO(b/33197203): LayoutParams.TYPE_AUTOFILL
+        params.type = LayoutParams.TYPE_SYSTEM_ALERT;
+        params.flags =
+                LayoutParams.SOFT_INPUT_STATE_UNCHANGED
+                | LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                | LayoutParams.FLAG_LAYOUT_NO_LIMITS
+                | LayoutParams.FLAG_NOT_FOCUSABLE
+                | LayoutParams.FLAG_NOT_TOUCH_MODAL
+                | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
+        params.gravity = Gravity.TOP | Gravity.LEFT;
+        params.width = LayoutParams.WRAP_CONTENT;
+        params.height = LayoutParams.WRAP_CONTENT;
+        return params;
+    }
+
+    /** FrameLayout that listens for touch events removes itself if the touch event is outside. */
+    private final class SelfRemovingView extends FrameLayout {
+        public SelfRemovingView(Context context) {
+            super(context);
+        }
+
+        @Override
+        public boolean onTouchEvent(MotionEvent event) {
+            if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
+                hide();
+                return true;
+            } else {
+                return super.onTouchEvent(event);
+            }
+        }
+    }
+}
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
index 6779657..8ce5278 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerService.java
@@ -21,6 +21,7 @@
 import static android.view.View.AUTO_FILL_FLAG_TYPE_FILL;
 
 import android.Manifest;
+import android.app.ActivityManagerInternal;
 import android.app.AppGlobals;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -31,7 +32,6 @@
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Binder;
-import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -39,16 +39,15 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
-import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.service.autofill.IAutoFillManagerService;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
+import android.util.LocalLog;
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.util.TimeUtils;
 import android.view.autofill.AutoFillId;
 
 import com.android.internal.annotations.GuardedBy;
@@ -56,10 +55,12 @@
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.os.SomeArgs;
 import com.android.server.FgThread;
+import com.android.server.LocalServices;
 import com.android.server.SystemService;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.List;
 
 /**
  * Entry point service for auto-fill management.
@@ -76,7 +77,8 @@
     private static final long SERVICE_BINDING_LIFETIME_MS = 5 * DateUtils.MINUTE_IN_MILLIS;
 
     protected static final int MSG_UNBIND = 1;
-    protected static final int MSG_SHOW_AUTO_FILL = 2;
+    protected static final int MSG_REQUEST_AUTO_FILL_FOR_USER = 2;
+    protected static final int MSG_REQUEST_AUTO_FILL = 3;
 
     private final AutoFillManagerServiceStub mServiceStub;
     private final AutoFillUI mUi;
@@ -91,18 +93,29 @@
         public void executeMessage(Message msg) {
             switch (msg.what) {
                 case MSG_UNBIND: {
-                    removeStaleServiceForUser(msg.arg1);
+                    synchronized (mLock) {
+                        removeCachedServiceLocked(msg.arg1);
+                    }
                     return;
-                } case MSG_SHOW_AUTO_FILL: {
+                } case MSG_REQUEST_AUTO_FILL_FOR_USER: {
+                    final int userId = msg.arg1;
+                    final int flags = msg.arg2;
+                    handleAutoFillForUser(userId, flags);
+                    return;
+                } case MSG_REQUEST_AUTO_FILL: {
                     final SomeArgs args = (SomeArgs) msg.obj;
-                    showAutoFillInput(msg.arg1, (AutoFillId) args.arg1, (Rect) args.arg2);
+                    final int userId = msg.arg1;
+                    final int flags = msg.arg2;
+                    final IBinder activityToken = (IBinder) args.arg1;
+                    final AutoFillId autoFillId = (AutoFillId) args.arg2;
+                    final Rect bounds = (Rect) args.arg3;
+                    handleAutoFill(activityToken, userId, autoFillId, bounds, flags);
                     return;
                 } default: {
                     Slog.w(TAG, "Invalid message: " + msg);
                 }
             }
         }
-
     };
 
     private HandlerCaller mHandlerCaller;
@@ -124,6 +137,9 @@
     @GuardedBy("mLock")
     private SparseArray<AutoFillManagerServiceImpl> mServicesCache = new SparseArray<>();
 
+    // TODO(b/33197203): set a different max (or disable it) on low-memory devices.
+    private final LocalLog mRequestsHistory = new LocalLog(100);
+
     public AutoFillManagerService(Context context) {
         super(context);
 
@@ -167,11 +183,11 @@
         if (DEBUG) Slog.d(TAG, "getServiceComponentForUser(" + userId + "): component="
                 + serviceComponent + ", info: " + serviceInfo);
         if (serviceInfo == null) {
-            Slog.w(TAG, "no service info for " + serviceComponent);
+            if (DEBUG) Slog.d(TAG, "no service info for " + serviceComponent);
             return null;
         }
-        return new AutoFillManagerServiceImpl(this, mUi, mContext, mLock, FgThread.getHandler(),
-                userId, serviceInfo.applicationInfo.uid, serviceComponent,
+        return new AutoFillManagerServiceImpl(this, mUi, mContext, mLock, mRequestsHistory,
+                FgThread.getHandler(), userId, serviceInfo.applicationInfo.uid, serviceComponent,
                 SERVICE_BINDING_LIFETIME_MS);
     }
 
@@ -199,87 +215,92 @@
         }
         // Keep service connection alive for a while, in case user needs to interact with it
         // (for example, to save the data that was inputted in)
+        if (mHandlerCaller.hasMessages(MSG_UNBIND)) {
+            mHandlerCaller.removeMessages(MSG_UNBIND);
+        }
         mHandlerCaller.sendMessageDelayed(mHandlerCaller.obtainMessageI(MSG_UNBIND, userId),
                 SERVICE_BINDING_LIFETIME_MS);
         return service;
     }
 
     /**
-     * Removes a cached service, but respecting its TTL.
+     * Removes a cached service for a given user.
      */
-    private void removeStaleServiceForUser(int userId) {
-        synchronized (mLock) {
-            removeCachedService(userId, false);
-        }
-    }
-
-    /**
-     * Removes a cached service, even if it has TTL.
-     */
-    void removeCachedServiceForUserLocked(int userId) {
-        removeCachedService(userId, true);
-    }
-
-    private void removeCachedService(int userId, boolean force) {
+    void removeCachedServiceLocked(int userId) {
         if (DEBUG) Log.d(TAG, "removing cached service for userId " + userId);
         final AutoFillManagerServiceImpl service = mServicesCache.get(userId);
         if (service == null) {
-            Log.w(TAG, "removeCachedServiceForUser(): no cached service for userId " + userId);
-            return;
-        }
-        if (!force) {
-            // Check TTL first.
-            final long now = SystemClock.uptimeMillis();
-            if (service.mEstimateTimeOfDeath > now) {
-                if (DEBUG) {
-                    final StringBuilder msg = new StringBuilder("service has some TTL left: ");
-                    TimeUtils.formatDuration(service.mEstimateTimeOfDeath - now, msg);
-                    Log.d(TAG, msg.toString());
-                }
-                return;
+            if (DEBUG) {
+                Log.d(TAG, "removeCachedServiceForUser(): no cached service for userId " + userId);
             }
+            return;
         }
         mServicesCache.delete(userId);
         service.stopLocked();
-
     }
 
-
-    private void requestAutoFillLocked(IBinder activityToken, int userId, Bundle extras,
-            int flags) {
-        final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId);
-        if (service != null) {
-            service.requestAutoFill(activityToken, extras, flags);
+    private void handleAutoFill(IBinder activityToken, int userId, AutoFillId autoFillId,
+            Rect bounds, int flags) {
+        synchronized (mLock) {
+            final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId);
+            if (service != null) {
+                // TODO(b/33197203): must pass AUTO_FILL_FLAG_TYPE_FILL because AM is expecting
+                // either that flag or AUTO_FILL_FLAG_TYPE_SAVE; should go away once save is
+                // refactored
+                flags |= AUTO_FILL_FLAG_TYPE_FILL;
+                service.requestAutoFillLocked(activityToken, autoFillId, bounds, flags);
+            }
         }
     }
 
-    private void showAutoFillInput(int userId, AutoFillId id, Rect rect) {
-        if (DEBUG) Slog.d(TAG, "handler.showAutoFillInput(): id=" + id + ", rect=" + rect);
-
+    private void handleAutoFillForUser(int userId, int flags) {
+        if (DEBUG) {
+            Slog.d(TAG, "handler.requestAutoFillForUser(): id=" + userId + ", flags=" + flags);
+        }
+        final List<IBinder> topActivities = LocalServices
+                .getService(ActivityManagerInternal.class).getTopVisibleActivities();
+        if (DEBUG)
+            Slog.d(TAG, "Top activities (" + topActivities.size() + "): " + topActivities);
+        if (topActivities.isEmpty()) {
+            Slog.w(TAG, "Could not get top activity");
+            return;
+        }
+        final IBinder activityToken = topActivities.get(0);
         synchronized (mLock) {
-            requestAutoFillLocked(null, userId, null, AUTO_FILL_FLAG_TYPE_FILL);
+            final AutoFillManagerServiceImpl service = getServiceForUserLocked(userId);
+            if (service == null) {
+                Slog.w(TAG, "no service for user " + userId);
+                return;
+            }
+            service.requestAutoFillLocked(activityToken, null, null, flags);
         }
     }
 
     final class AutoFillManagerServiceStub extends IAutoFillManagerService.Stub {
 
         @Override
-        public void showAutoFillInput(AutoFillId id, Rect boundaries) {
-            if (DEBUG) Slog.d(TAG, "showAutoFillInput(): id=" + id + ", boundaries=" + boundaries);
+        public void requestAutoFill(AutoFillId id, Rect bounds, int flags) {
+            if (DEBUG) Slog.d(TAG, "requestAutoFill: flags=" + flags + ", autoFillId=" + id
+                    + ", bounds=" + bounds);
 
-            // TODO(b/33197203): fail if it's not called by same uid as the top activity
-            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIOO(MSG_SHOW_AUTO_FILL,
-                    UserHandle.getCallingUserId(), id, boundaries));
+            // Make sure its called by the top activity.
+            final int uid = Binder.getCallingUid();
+            final IBinder activityToken = LocalServices.getService(ActivityManagerInternal.class)
+                        .getTopVisibleActivity(uid);
+            if (activityToken == null) {
+                throw new SecurityException("uid " + uid + " does not own the top activity");
+            }
+
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIIOOO(MSG_REQUEST_AUTO_FILL,
+                    UserHandle.getCallingUserId(), flags, activityToken, id, bounds));
         }
 
         @Override
-        public void requestAutoFill(IBinder activityToken, int userId, Bundle extras, int flags) {
-            if (DEBUG) Slog.d(TAG, "requestAutoFill: flags=" + flags + ", userId=" + userId);
+        public void requestAutoFillForUser(int userId, int flags) {
             mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
 
-            synchronized (mLock) {
-                requestAutoFillLocked(activityToken, userId, extras, flags);
-            }
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageII(
+                    MSG_REQUEST_AUTO_FILL_FOR_USER, userId, flags));
         }
 
         @Override
@@ -305,6 +326,9 @@
                     }
                 }
             }
+            mUi.dump(pw);
+            pw.println("Requests history:");
+            mRequestsHistory.reverseDump(fd, pw, args);
         }
 
         @Override
@@ -313,7 +337,6 @@
             (new AutoFillManagerServiceShellCommand(this)).exec(
                     this, in, out, err, args, callback, resultReceiver);
         }
-
     }
 
     private final class SettingsObserver extends ContentObserver {
@@ -328,7 +351,7 @@
         public void onChange(boolean selfChange, Uri uri, int userId) {
             if (DEBUG) Slog.d(TAG, "settings (" + uri + " changed for " + userId);
             synchronized (mLock) {
-                removeCachedServiceForUserLocked(userId);
+                removeCachedServiceLocked(userId);
             }
         }
     }
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
index 83faf1b..0dd891c 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceImpl.java
@@ -16,12 +16,18 @@
 
 package com.android.server.autofill;
 
-import static com.android.server.autofill.AutoFillManagerService.DEBUG;
+import static android.service.autofill.AutoFillService.FLAG_AUTHENTICATION_ERROR;
+import static android.service.autofill.AutoFillService.FLAG_AUTHENTICATION_REQUESTED;
+import static android.service.autofill.AutoFillService.FLAG_AUTHENTICATION_SUCCESS;
+import static android.view.View.AUTO_FILL_FLAG_TYPE_SAVE;
+import static android.view.autofill.AutoFillManager.FLAG_UPDATE_UI_HIDE;
+
+import static com.android.server.autofill.Helper.DEBUG;
+import static com.android.server.autofill.Helper.bundleToString;
 
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.ActivityManager;
-import android.app.ActivityManagerInternal;
 import android.app.IActivityManager;
 import android.app.assist.AssistStructure;
 import android.content.BroadcastReceiver;
@@ -31,12 +37,17 @@
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
-import android.icu.text.DateFormat;
+import android.graphics.Rect;
+import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.IFingerprintService;
+import android.hardware.fingerprint.IFingerprintServiceReceiver;
+import android.os.Binder;
 import android.os.Bundle;
 import android.os.DeadObjectException;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.service.autofill.AutoFillService;
@@ -45,6 +56,8 @@
 import android.service.autofill.IAutoFillServerCallback;
 import android.service.autofill.IAutoFillService;
 import android.service.voice.VoiceInteractionSession;
+import android.util.LocalLog;
+import android.util.Log;
 import android.util.PrintWriterPrinter;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -55,11 +68,10 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.IResultReceiver;
-import com.android.server.LocalServices;
 
 import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
 import java.util.Arrays;
-import java.util.Date;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -73,11 +85,12 @@
     private static final String TAG = "AutoFillManagerServiceImpl";
 
     /** Used do assign ids to new ServerCallback instances. */
-    private static int sServerCallbackCounter = 0;
+    private static int sSessionIdCounter = 0;
 
     private final int mUserId;
     private final int mUid;
     private final ComponentName mComponent;
+    private final String mComponentName;
     private final Context mContext;
     private final IActivityManager mAm;
     private final Object mLock;
@@ -85,14 +98,15 @@
     private final AutoFillManagerService mManagerService;
     private final AutoFillUI mUi;
 
-    // TODO(b/33197203): improve its usage
-    // - set maximum number of entries
-    // - disable on low-memory devices.
-    private final List<String> mRequestHistory = new LinkedList<>();
+    // Token used for fingerprint authentication
+    // TODO(b/33197203): create on demand?
+    private final IBinder mAuthToken = new Binder();
 
     @GuardedBy("mLock")
     private final List<QueuedRequest> mQueuedRequests = new LinkedList<>();
 
+    private final LocalLog mRequestsHistory;
+
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -106,13 +120,15 @@
     };
 
     /**
-     * Cache of pending ServerCallbacks, keyed by {@link ServerCallback#id}.
+     * Cache of pending {@link Session}s, keyed by {@link Session#mId}.
      *
-     * <p>They're kept until the AutoFillService handles a request, or an error occurs.
+     * <p>They're kept until the {@link AutoFillService} finished handling a request, an error
+     * occurs, or the session times out.
      */
-    // TODO(b/33197203): need to make sure service is bound while callback is pending
+    // TODO(b/33197203): need to make sure service is bound while callback is pending and/or
+    // use WeakReference
     @GuardedBy("mLock")
-    private static final SparseArray<ServerCallback> mServerCallbacks = new SparseArray<>();
+    private static final SparseArray<Session> mSessions = new SparseArray<>();
 
     private final ServiceConnection mConnection = new ServiceConnection() {
         @Override
@@ -130,9 +146,10 @@
                     if (DEBUG) Slog.d(TAG, "queued requests:" + mQueuedRequests.size());
                 }
                 for (final QueuedRequest request: mQueuedRequests) {
-                    requestAutoFillLocked(request.activityToken, request.extras, request.flags,
-                            false);
+                    requestAutoFillLocked(request.activityToken, request.autoFillId,
+                            request.bounds, request.flags, false);
                 }
+                mQueuedRequests.clear();
             }
         }
 
@@ -141,15 +158,14 @@
             if (DEBUG) Slog.d(TAG, name + " disconnected");
             synchronized (mLock) {
                 mService = null;
-                mManagerService.removeCachedServiceForUserLocked(mUserId);
+                mManagerService.removeCachedServiceLocked(mUserId);
             }
         }
     };
 
-
     /**
      * Receiver of assist data from the app's {@link Activity}, uses the {@code resultData} as
-     * the {@link ServerCallback#id}.
+     * the {@link Session#mId}.
      */
     private final IResultReceiver mAssistReceiver = new IResultReceiver.Stub() {
         @Override
@@ -165,37 +181,41 @@
                     .getParcelable(VoiceInteractionSession.KEY_STRUCTURE);
             final int flags = resultData.getInt(VoiceInteractionSession.KEY_FLAGS, 0);
 
-            final ServerCallback serverCallback;
+            final Session session;
             synchronized (mLock) {
-                serverCallback = mServerCallbacks.get(resultCode);
-                if (serverCallback == null) {
+                session = mSessions.get(resultCode);
+                if (session == null) {
                     Slog.w(TAG, "no server callback for id " + resultCode);
                     return;
                 }
-                serverCallback.appCallback = IAutoFillAppCallback.Stub.asInterface(appBinder);
+                session.setAppCallback(appBinder);
             }
-            mService.autoFill(structure, serverCallback, serverCallback.extras, flags);
+            mService.autoFill(structure, session.mServerCallback, flags);
         }
     };
 
     @GuardedBy("mLock")
     private IAutoFillService mService;
+    @GuardedBy("mLock")
     private boolean mBound;
+    @GuardedBy("mLock")
     private boolean mValid;
 
     // Estimated time when the service will be evicted from the cache.
     long mEstimateTimeOfDeath;
 
     AutoFillManagerServiceImpl(AutoFillManagerService managerService, AutoFillUI ui,
-            Context context, Object lock, Handler handler, int userId, int uid,
-            ComponentName component, long ttl) {
+            Context context, Object lock, LocalLog requestsHistory, Handler handler, int userId,
+            int uid, ComponentName component, long ttl) {
         mManagerService = managerService;
         mUi = ui;
         mContext = context;
         mLock = lock;
+        mRequestsHistory = requestsHistory;
         mUserId = userId;
         mUid = uid;
         mComponent = component;
+        mComponentName = mComponent.flattenToShortString();
         mAm = ActivityManager.getService();
         setLifeExpectancy(ttl);
 
@@ -243,60 +263,86 @@
     /**
      * Asks service to auto-fill an activity.
      *
-     * @param activityToken activity token
-     * @param extras bundle to be passed to the {@link AutoFillService} method.
+     * @param activityToken activity token.
+     * @param autoFillId id of the view that requested auto-fill.
      * @param flags optional flags.
      */
-    void requestAutoFill(@Nullable IBinder activityToken, @Nullable Bundle extras, int flags) {
-        synchronized (mLock) {
-            if (!mBound) {
-                Slog.w(TAG, "requestAutoFill() failed because it's not bound to service");
-                return;
-            }
+    void requestAutoFillLocked(IBinder activityToken, @Nullable AutoFillId autoFillId,
+            @Nullable Rect bounds, int flags) {
+        if (!mBound) {
+            Slog.w(TAG, "requestAutoFill() failed because it's not bound to service");
+            return;
         }
 
-        // TODO(b/33197203): activityToken should probably not be null, but we need to wait until
-        // the UI is triggering the call (for now it's trough 'adb shell cmd autofill request'
-        if (activityToken == null) {
-            // Let's get top activities from all visible stacks.
-
-            // TODO(b/33197203): overload getTopVisibleActivities() to take userId, otherwise it
-            // could return activities for different users when a work profile app is displayed in
-            // another window (in a multi-window environment).
-            final List<IBinder> topActivities = LocalServices
-                    .getService(ActivityManagerInternal.class).getTopVisibleActivities();
-            if (DEBUG)
-                Slog.d(TAG, "Top activities (" + topActivities.size() + "): " + topActivities);
-            if (topActivities.isEmpty()) {
-                Slog.w(TAG, "Could not get top activity");
-                return;
-            }
-            activityToken = topActivities.get(0);
-        }
-
-        final String historyItem =
-                DateFormat.getDateTimeInstance().format(new Date()) + " - " + activityToken;
-        synchronized (mLock) {
-            mRequestHistory.add(historyItem);
-            requestAutoFillLocked(activityToken, extras, flags, true);
-        }
+        requestAutoFillLocked(activityToken, autoFillId, bounds, flags, true);
     }
 
-    private void requestAutoFillLocked(IBinder activityToken, @Nullable Bundle extras, int flags,
-            boolean queueIfNecessary) {
+    private void requestAutoFillLocked(IBinder activityToken, AutoFillId autoFillId, Rect bounds,
+            int flags, boolean queueIfNecessary) {
         if (mService == null) {
             if (!queueIfNecessary) {
                 Slog.w(TAG, "requestAutoFillLocked(): service is null");
                 return;
             }
-            if (DEBUG) Slog.d(TAG, "requestAutoFill(): service not set yet, queuing it");
-            mQueuedRequests.add(new QueuedRequest(activityToken, extras, flags));
+            if (DEBUG) Slog.d(TAG, "requestAutoFillLocked(): service not set yet, queuing it");
+            mQueuedRequests.add(new QueuedRequest(activityToken, autoFillId, bounds, flags));
+            return;
+        }
+        if (activityToken == null) {
+            // Sanity check
+            Slog.wtf(TAG, "requestAutoFillLocked(): null activityToken");
             return;
         }
 
-        final int callbackId = ++sServerCallbackCounter;
-        final ServerCallback serverCallback = new ServerCallback(callbackId, extras);
-        mServerCallbacks.put(callbackId, serverCallback);
+        final Session session = getSessionByTokenLocked(activityToken);
+
+        if (session != null) {
+            // Session already exist, update UI instead...
+            /*
+             * TODO(b/33197203): currently, it's always reusing the session, regardless of the
+             * requested autoFillId, but it should start a new session for views that
+             * were not part of the initial auto-fill dataset returned by the service. For example:
+             *
+             * 1.Activity has 4 fields, `first_name`, `last_name`, and `address`.
+             * 2.User taps `first_name`.
+             * 3.Service returns a dataset with ids for `first_name` and `last_name`.
+             * 4.When user taps `first_name` (again) or `last_name`, session should be reused, but
+             * when user taps `address`, it should start a new session (since that field was
+             *   not part of the initial dataset).
+             *
+             * Similarly, once the activity is auto-filled, the flag logic should be reset (so if
+             * the user taps the view again, a new auto-fill request is made)
+             */
+            if (DEBUG) {
+                Slog.d(TAG, "requestAutoFillLocked(): reusing session for token "
+                        + activityToken + ", id " + autoFillId + " and flags " + flags);
+            }
+
+            if ((flags & FLAG_UPDATE_UI_HIDE) != 0) {
+                // TODO(b/33197203): handle it?
+                if (DEBUG) Slog.d(TAG, "ignoring FLAG_UPDATE_UI_HIDE request for " + autoFillId);
+
+                return;
+            }
+
+            session.mCurrentAutoFillId = autoFillId;
+            session.mCurrentBounds = bounds;
+            mUi.showResponse(mUserId, session.mId, autoFillId, bounds, session.mCurrentResponse);
+            return;
+        }
+
+        final int sessionId = ++sSessionIdCounter;
+        if (DEBUG) {
+            Slog.d(TAG, "requestAutoFillLocked(): new session (id=" + sessionId + " for token "
+                    + activityToken + " and autoFillId " + autoFillId);
+        }
+
+        final Session newSession = new Session(sessionId, activityToken, autoFillId, bounds);
+        mSessions.put(sessionId, newSession);
+
+        final String historyItem = "s=" + mComponentName + " u=" + mUserId + " f=" + flags
+                + " a=" + activityToken + " i=" + autoFillId + " b=" + bounds;
+        mRequestsHistory.log(historyItem);
 
         /*
          * TODO(b/33197203): apply security checks below:
@@ -307,16 +353,85 @@
          */
         try {
             // TODO(b/33197203): add MetricsLogger call
-            if (!mAm.requestAutoFillData(mAssistReceiver, null, callbackId, activityToken, flags)) {
+            if (!mAm.requestAutoFillData(mAssistReceiver, null, sessionId, activityToken, flags)) {
                 // TODO(b/33197203): might need a way to warn user (perhaps a new method on
                 // AutoFillService).
                 Slog.w(TAG, "failed to request auto-fill data for " + activityToken);
             }
         } catch (RemoteException e) {
-            // Should happen, it's a local call.
+            // Should not happen, it's a local call.
         }
     }
 
+    /**
+     * Called by UI to trigger a save request to the service.
+     */
+    void requestSaveLocked(int sessionId) {
+        // TODO(b/33197203): add MetricsLogger call
+        // TODO(b/33197203): use handler?
+        // TODO(b/33197203): show error on UI on Slog.w situations below???
+
+        if (mService == null) {
+            Slog.w(TAG, "requestSave(): service is null");
+            return;
+        }
+        final Session session = mSessions.get(sessionId);
+        if (session == null) {
+            Slog.w(TAG, "requestSave(): no session with id " + sessionId);
+            return;
+        }
+        final IBinder activityToken = session.mActivityToken.get();
+        if (activityToken == null) {
+            Slog.w(TAG, "activity token for session " + sessionId + " already GCed");
+            return;
+        }
+
+        /*
+         * TODO(b/33197203): apply security checks below:
+         * - checks if disabled by secure settings / device policy
+         * - log operation using noteOp()
+         * - check flags
+         * - display disclosure if needed
+         */
+        try {
+            /* TODO(b/33197203): refactor save logic so it uses a cached AssistStructure, and get
+               the extras to be sent to the service based on the response / dataset in the session.
+               Something like:
+           final Bundle extras = (responseExtras == null && datasetExtras == null)
+                  ? null : new Bundle();
+            if (responseExtras != null) {
+                if (DEBUG) Slog.d(TAG, "response extras on save notification: " +
+                        bundleToString(responseExtras));
+                extras.putBundle(AutoFillService.EXTRA_RESPONSE_EXTRAS, responseExtras);
+            }
+            if (datasetExtras != null) {
+                if (DEBUG) Slog.d(TAG, "dataset extras on save notification: " +
+                        bundleToString(datasetExtras));
+                extras.putBundle(AutoFillService.EXTRA_DATASET_EXTRAS, datasetExtras);
+            }
+
+             */
+
+            if (!mAm.requestAutoFillData(mAssistReceiver, null, sessionId, activityToken,
+                    AUTO_FILL_FLAG_TYPE_SAVE)) {
+                Slog.w(TAG, "failed to save for " + activityToken);
+            }
+        } catch (RemoteException e) {
+            // Should not happen, it's a local call.
+        }
+    }
+
+    private Session getSessionByTokenLocked(IBinder activityToken) {
+        final int size = mSessions.size();
+        for (int i = 0; i < size; i++) {
+            final Session session = mSessions.valueAt(i);
+            if (activityToken.equals(session.mActivityToken.get())) {
+                return session;
+            }
+        }
+        return null;
+    }
+
     void stopLocked() {
         if (DEBUG) Slog.d(TAG, "stopLocked()");
 
@@ -347,39 +462,74 @@
     /**
      * Called by {@link AutoFillUI} to fill an activity after the user selected a dataset.
      */
-    void autoFillApp(int callbackId, Dataset dataset) {
+    void autoFillApp(int sessionId, Dataset dataset) {
         // TODO(b/33197203): add MetricsLogger call
 
         if (dataset == null) {
-            Slog.w(TAG, "autoFillApp(): no dataset for callback id " + callbackId);
+            Slog.w(TAG, "autoFillApp(): no dataset for callback id " + sessionId);
             return;
         }
 
-        final ServerCallback serverCallback;
+
+        final Session session;
         synchronized (mLock) {
-            serverCallback = mServerCallbacks.get(callbackId);
-            if (serverCallback == null) {
-                Slog.w(TAG, "autoFillApp(): no server callback with id " + callbackId);
+            session = mSessions.get(sessionId);
+            if (session == null) {
+                Slog.w(TAG, "autoFillApp(): no session with id " + sessionId);
                 return;
             }
-            if (serverCallback.appCallback == null) {
-                Slog.w(TAG, "autoFillApp(): no app callback for server callback " + callbackId);
+            if (session.mAppCallback == null) {
+                Slog.w(TAG, "autoFillApp(): no app callback for session " + sessionId);
                 return;
             }
+
             // TODO(b/33197203): use a handler?
-            try {
-                if (DEBUG) Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset);
-                serverCallback.appCallback.autoFill(dataset);
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Error auto-filling activity: " + e);
-            }
-            removeServerCallbackLocked(callbackId);
+            session.autoFill(dataset);
         }
     }
 
-    void removeServerCallbackLocked(int id) {
-        if (DEBUG) Slog.d(TAG, "Removing " + id + " from server callbacks");
-        mServerCallbacks.remove(id);
+    void removeSessionLocked(int id) {
+        if (DEBUG) Slog.d(TAG, "Removing session " + id);
+        mSessions.remove(id);
+
+        // TODO(b/33197203): notify mService so it can invalidate the FillCallback / SaveCallback?
+    }
+
+    /**
+     * Notifies the result of a {@link FillResponse} authentication request to the service.
+     *
+     * <p>Typically called by the UI after user taps the "Tap to autofill" affordance, or after user
+     * used the fingerprint sensors to authenticate.
+     */
+    void notifyResponseAuthenticationResult(Bundle extras, int flags) {
+        if (DEBUG) Slog.d(TAG, "notifyResponseAuthenticationResult(): flags=" + flags
+                + ", extras=" + bundleToString(extras));
+
+        synchronized (mLock) {
+            try {
+                mService.authenticateFillResponse(extras, flags);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Error sending authentication result back to service: " + e);
+            }
+        }
+    }
+
+    /**
+     * Notifies the result of a {@link Dataset} authentication request to the service.
+     *
+     * <p>Typically called by the UI after user taps the "Tap to autofill" affordance, or after
+     * it gets the results from a fingerprint authentication.
+     */
+    void notifyDatasetAuthenticationResult(Bundle extras, int flags) {
+        if (DEBUG) Slog.d(TAG, "notifyDatasetAuthenticationResult(): flags=" + flags
+                + ", extras=" + bundleToString(extras));
+        synchronized (mLock) {
+            try {
+                mService.authenticateDataset(extras, flags);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Error sending authentication result back to service: " + e);
+            }
+        }
     }
 
     void dumpLocked(String prefix, PrintWriter pw) {
@@ -397,27 +547,20 @@
 
         pw.print(prefix); pw.print("mUserId="); pw.println(mUserId);
         pw.print(prefix); pw.print("mUid="); pw.println(mUid);
-        pw.print(prefix); pw.print("mComponent="); pw.println(mComponent.flattenToShortString());
+        pw.print(prefix); pw.print("mComponent="); pw.println(mComponentName);
+        pw.print(prefix); pw.print("mService: "); pw.println(mService);
         pw.print(prefix); pw.print("mBound="); pw.println(mBound);
-        pw.print(prefix); pw.print("mService="); pw.println(mService);
         pw.print(prefix); pw.print("mEstimateTimeOfDeath=");
             TimeUtils.formatDuration(mEstimateTimeOfDeath, SystemClock.uptimeMillis(), pw);
-        pw.println();
+            pw.println();
+        pw.print(prefix); pw.print("mAuthToken: "); pw.println(mAuthToken);
 
         if (DEBUG) {
             // ServiceInfo dump is too noisy and redundant (it can be obtained through other dumps)
-            pw.print(prefix); pw.println("Service info:");
+            pw.print(prefix); pw.println("ServiceInfo:");
             mInfo.getServiceInfo().dump(new PrintWriterPrinter(pw), prefix + prefix);
         }
 
-        if (mRequestHistory.isEmpty()) {
-            pw.print(prefix); pw.println("No history");
-        } else {
-            pw.print(prefix); pw.println("History:");
-            for (int i = 0; i < mRequestHistory.size(); i++) {
-                pw.print(prefix2); pw.print(i); pw.print(": "); pw.println(mRequestHistory.get(i));
-            }
-        }
         if (mQueuedRequests.isEmpty()) {
             pw.print(prefix); pw.println("No queued requests");
         } else {
@@ -427,94 +570,391 @@
             }
         }
 
-        pw.print(prefix); pw.print("sServerCallbackCounter="); pw.println(sServerCallbackCounter);
-        final int size = mServerCallbacks.size();
+        pw.print(prefix); pw.print("sSessionIdCounter="); pw.println(sSessionIdCounter);
+        final int size = mSessions.size();
         if (size == 0) {
-            pw.print(prefix); pw.println("No server callbacks");
+            pw.print(prefix); pw.println("No sessions");
         } else {
-            pw.print(prefix); pw.print(size); pw.println(" server callbacks:");
+            pw.print(prefix); pw.print(size); pw.println(" sessions:");
             for (int i = 0; i < size; i++) {
-                pw.print(prefix2); pw.print(mServerCallbacks.keyAt(i));
-                final ServerCallback callback = mServerCallbacks.valueAt(i);
-                if (callback.appCallback == null) {
-                    pw.println("(no appCallback)");
-                } else {
-                    pw.print(" (app callback: "); pw.print(callback.appCallback) ; pw.println(")");
-                }
+                pw.print(prefix); pw.print("#"); pw.println(i + 1);
+                mSessions.valueAt(i).dumpLocked(prefix2, pw);
             }
-            pw.println();
         }
     }
 
     @Override
     public String toString() {
-        return "[AutoFillManagerServiceImpl: userId=" + mUserId + ", uid=" + mUid
-                + ", component=" + mComponent.flattenToShortString() + "]";
+        return "AutoFillManagerServiceImpl: [userId=" + mUserId + ", uid=" + mUid
+                + ", component=" + mComponentName + "]";
     }
 
     private static final class QueuedRequest {
         final IBinder activityToken;
-        final Bundle extras;
+        final AutoFillId autoFillId;
+        final Rect bounds;
         final int flags;
 
-        QueuedRequest(IBinder activityToken, Bundle extras, int flags) {
+        QueuedRequest(IBinder activityToken, AutoFillId autoFillId, Rect bounds, int flags) {
             this.activityToken = activityToken;
-            this.extras = extras;
+            this.autoFillId = autoFillId;
+            this.bounds = bounds;
             this.flags = flags;
         }
 
         @Override
         public String toString() {
-            return "flags: " + flags + " token: " + activityToken;
+            if (!DEBUG) return super.toString();
+
+            return "QueuedRequest: [flags=" + flags + ", token=" + activityToken
+                    + ", id=" + autoFillId + ", bounds=" + bounds;
         }
     }
 
     /**
      * A bridge between the {@link AutoFillService} implementation and the activity being
      * auto-filled (represented through the {@link IAutoFillAppCallback}).
+     *
+     * <p>Although the auto-fill requests and callbacks are stateless from the service's point of
+     * view, we need to keep state in the framework side for cases such as authentication. For
+     * example, when service return a {@link FillResponse} that contains all the fields needed
+     * to fill the activity but it requires authentication first, that response need to be held
+     * until the user authenticates or it times out.
      */
-    private final class ServerCallback extends IAutoFillServerCallback.Stub {
+    // TODO(b/33197203): make sure sessions are removed (and tested by CTS):
+    // - On all authentication scenarios.
+    // - When user does not interact back after a while.
+    // - When service is unbound.
+    private final class Session {
 
-        private final int id;
-        private final Bundle extras;
-        private IAutoFillAppCallback appCallback;
+        private final int mId;
+        private final WeakReference<IBinder> mActivityToken;
 
-        private ServerCallback(int id, Bundle extras) {
-            this.id = id;
-            this.extras = extras;
+        private IAutoFillAppCallback mAppCallback;
+
+        // Current view where the auto-fill bar is displayed
+        @GuardedBy("mLock")
+        private AutoFillId mCurrentAutoFillId;
+        @GuardedBy("mLock")
+        private Rect mCurrentBounds;
+        @GuardedBy("mLock")
+        private FillResponse mCurrentResponse;
+
+        private final IFingerprintService mFingerprintService;
+
+        @GuardedBy("mLock")
+        private FillResponse mResponseRequiringAuth;
+        @GuardedBy("mLock")
+        private Dataset mDatasetRequiringAuth;
+
+        // Used to auto-fill the activity directly when the FillCallback.onResponse() is called as
+        // the result of a successful user authentication on service's side.
+        @GuardedBy("mLock")
+        private boolean mAutoFillDirectly;
+
+        // TODO(b/33197203): use handler to handle results?
+        // TODO(b/33197203): handle all callback methods and/or cancelation?
+        private IFingerprintServiceReceiver mServiceReceiver =
+                new IFingerprintServiceReceiver.Stub() {
+
+            @Override
+            public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
+                if (DEBUG) Slog.d(TAG, "onEnrollResult()");
+            }
+
+            @Override
+            public void onAcquired(long deviceId, int acquiredInfo, int vendorCode) {
+                if (DEBUG) Slog.d(TAG, "onAcquired()");
+            }
+
+            @Override
+            public void onAuthenticationSucceeded(long deviceId, Fingerprint fp, int userId) {
+                if (DEBUG) Slog.d(TAG, "onAuthenticationSucceeded(): " + fp.getGroupId());
+
+                // First, check what was authenticated, a response or a dataset.
+                // Then, decide how to handle it:
+                // - If service provided data, handle them directly.
+                // - Otherwise, notify service.
+
+                mAutoFillDirectly = true;
+
+                if (mDatasetRequiringAuth != null) {
+                    if (mDatasetRequiringAuth.isEmpty()) {
+                        notifyDatasetAuthenticationResult(mDatasetRequiringAuth.getExtras(),
+                                FLAG_AUTHENTICATION_SUCCESS);
+                    } else {
+                        autoFillAppLocked(mDatasetRequiringAuth, true);
+                    }
+                } else if (mResponseRequiringAuth != null) {
+                    final List<Dataset> datasets = mResponseRequiringAuth.getDatasets();
+                    if (datasets.isEmpty()) {
+                        notifyResponseAuthenticationResult(mResponseRequiringAuth.getExtras(),
+                                FLAG_AUTHENTICATION_SUCCESS);
+                    } else {
+                        showResponseLocked(mResponseRequiringAuth, true);
+                    }
+                } else {
+                    Slog.w(TAG, "onAuthenticationSucceeded(): no response or dataset");
+                }
+
+                mUi.dismissFingerprintRequest(mUserId, true);
+            }
+
+            @Override
+            public void onAuthenticationFailed(long deviceId) {
+                if (DEBUG) Slog.d(TAG, "onAuthenticationFailed()");
+                // Do nothing - onError() will be called after a few failures...
+            }
+
+            @Override
+            public void onError(long deviceId, int error, int vendorCode) {
+                if (DEBUG) Slog.d(TAG, "onError()");
+
+                // Notify service so it can fallback to its own authentication
+                if (mDatasetRequiringAuth != null) {
+                    notifyDatasetAuthenticationResult(mDatasetRequiringAuth.getExtras(),
+                            FLAG_AUTHENTICATION_ERROR);
+                } else if (mResponseRequiringAuth != null) {
+                    notifyResponseAuthenticationResult(mResponseRequiringAuth.getExtras(),
+                            FLAG_AUTHENTICATION_ERROR);
+                } else {
+                    Slog.w(TAG, "onError(): no response or dataset");
+                }
+
+                mUi.dismissFingerprintRequest(mUserId, false);
+            }
+
+            @Override
+            public void onRemoved(long deviceId, int fingerId, int groupId, int remaining) {
+                if (DEBUG) Slog.d(TAG, "onRemoved()");
+            }
+
+            @Override
+            public void onEnumerated(long deviceId, int fingerId, int groupId, int remaining) {
+                if (DEBUG) Slog.d(TAG, "onEnumerated()");
+            }
+        };
+
+        private IAutoFillServerCallback mServerCallback = new IAutoFillServerCallback.Stub() {
+            @Override
+            public void showResponse(FillResponse response) {
+                // TODO(b/33197203): add MetricsLogger call
+                if (response == null) {
+                    if (DEBUG) Slog.d(TAG, "showResponse(): null response");
+
+                    removeSelf();
+                    return;
+                }
+
+                synchronized (mLock) {
+                    showResponseLocked(response, response.isAuthRequired());
+                }
+            }
+
+            @Override
+            public void showError(CharSequence message) {
+                // TODO(b/33197203): add MetricsLogger call
+                if (DEBUG) Slog.d(TAG, "showError(): " + message);
+
+                mUi.showError(message);
+
+                removeSelf();
+            }
+
+            @Override
+            public void highlightSavedFields(AutoFillId[] ids) {
+                // TODO(b/33197203): add MetricsLogger call
+                if (DEBUG) Slog.d(TAG, "highlightSavedFields(): " + Arrays.toString(ids));
+
+                mUi.highlightSavedFields(ids);
+
+                removeSelf();
+            }
+
+            @Override
+            public void unlockFillResponse(int flags) {
+                // TODO(b/33197203): add proper MetricsLogger calls?
+                if (DEBUG) Log.d(TAG, "unlockUser(): flags=" + flags);
+
+                synchronized (mLock) {
+                    if ((flags & FLAG_AUTHENTICATION_SUCCESS) != 0) {
+                        if (mResponseRequiringAuth == null) {
+                            Log.wtf(TAG, "unlockUser(): no mResponseRequiringAuth on flags "
+                                    + flags);
+                            removeSelf();
+                            return;
+                        }
+                        final List<Dataset> datasets = mResponseRequiringAuth.getDatasets();
+                        if (datasets.isEmpty()) {
+                            Log.w(TAG, "unlockUser(): no dataset on previous response: "
+                                    + mResponseRequiringAuth);
+                            removeSelf();
+                            return;
+                        }
+                        mAutoFillDirectly = true;
+                        showResponseLocked(mResponseRequiringAuth, false);
+                    }
+                    // TODO(b/33197203): show UI error on authentication failure?
+                    // Or let service handle it?
+                }
+            }
+
+            @Override
+            public void unlockDataset(Dataset dataset, int flags) {
+                // TODO(b/33197203): add proper MetricsLogger calls?
+                if (DEBUG) Log.d(TAG, "unlockDataset(): dataset=" + dataset + ", flags=" + flags);
+
+                if ((flags & FLAG_AUTHENTICATION_SUCCESS) != 0) {
+                    autoFillAppLocked(dataset != null ? dataset : mDatasetRequiringAuth, true);
+                    return;
+                }
+                removeSelf();
+            }
+        };
+
+        private Session(int id, IBinder activityToken, AutoFillId autoFillId, Rect bounds) {
+            this.mId = id;
+            this.mActivityToken = new WeakReference<>(activityToken);
+            this.mCurrentAutoFillId = autoFillId;
+            this.mCurrentBounds = bounds;
+            this.mFingerprintService = IFingerprintService.Stub
+                    .asInterface(ServiceManager.getService("fingerprint"));
         }
 
-        @Override
-        public void showResponse(FillResponse response) {
-            // TODO(b/33197203): add MetricsLogger call
-            if (DEBUG) Slog.d(TAG, "showResponse(): " + response);
-
-            mUi.showOptions(mUserId, id, response);
+        void setAppCallback(IBinder appBinder) {
+            try {
+                appBinder.linkToDeath(() -> {
+                    if (DEBUG) Slog.d(TAG, "app callback died");
+                    // TODO(b/33197203): more cleanup here?
+                    mAppCallback = null;
+                }, 0);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "linkToDeath() failed: " + e);
+            }
+            mAppCallback = IAutoFillAppCallback.Stub.asInterface(appBinder);
         }
 
-        @Override
-        public void showError(String message) {
-            // TODO(b/33197203): add MetricsLogger call
-            if (DEBUG) Slog.d(TAG, "showError(): " + message);
+        private void showResponseLocked(FillResponse response, boolean authRequired) {
+            if (DEBUG) Slog.d(TAG, "showResponse(directly=" + mAutoFillDirectly
+                    + ", authRequired=" + authRequired +"):" + response);
 
-            mUi.showError(message);
+            if (mAutoFillDirectly && response != null) {
+                final List<Dataset> datasets = response.getDatasets();
+                if (datasets.size() == 1) {
+                    // User authenticated and provider returned just 1 dataset - auto-fill it now!
+                    final Dataset dataset = datasets.get(0);
+                    if (DEBUG) Slog.d(TAG, "auto-filling directly from auth: " + dataset);
 
-            removeSelf();
+                    autoFillAppLocked(dataset, true);
+                    return;
+                }
+            }
+
+            if (!authRequired) {
+                // TODO(b/33197203): add MetricsLogger call
+                mCurrentResponse = response;
+                mUi.showResponse(mUserId, mId, mCurrentAutoFillId, mCurrentBounds, mCurrentResponse);
+                return;
+            }
+
+            // Handles response that requires authentication.
+            // TODO(b/33197203): add MetricsLogger call, including if fingerprint requested
+
+            mResponseRequiringAuth = response;
+            final boolean requiresFingerprint = response.hasCryptoObject();
+            if (requiresFingerprint) {
+                // TODO(b/33197203): check if fingerprint is available first and call error callback
+                // with FLAG_FINGERPRINT_AUTHENTICATION_NOT_AVAILABLE if it's not.
+                // Start scanning for the fingerprint.
+                scanFingerprint(response.getCryptoObjectOpId());
+            }
+            // Displays the message asking the user to tap (or fingerprint) for AutoFill.
+            mUi.showFillResponseAuthenticationRequest(mUserId, mId, requiresFingerprint,
+                    response.getExtras(), response.getFlags());
         }
 
-        @Override
-        public void highlightSavedFields(AutoFillId[] ids) {
+        void autoFill(Dataset dataset) {
+            synchronized (mLock) {
+                // Autofill it directly...
+                if (!dataset.isAuthRequired()) {
+                    autoFillAppLocked(dataset, true);
+                    return;
+                }
+
+                // ...or handle authentication.
+
+                mDatasetRequiringAuth = dataset;
+                final boolean requiresFingerprint = dataset.hasCryptoObject();
+                if (requiresFingerprint) {
+                    // TODO(b/33197203): check if fingerprint is available first and call error
+                    // callback with FLAG_FINGERPRINT_AUTHENTICATION_NOT_AVAILABLE if it's not.
+                    // Start scanning for the fingerprint.
+                    scanFingerprint(dataset.getCryptoObjectOpId());
+                    // Displays the message asking the user to tap (or fingerprint) for AutoFill.
+                    mUi.showDatasetFingerprintAuthenticationRequest(dataset);
+                } else {
+                    try {
+                        mService.authenticateDataset(dataset.getExtras(),
+                                FLAG_AUTHENTICATION_REQUESTED);
+                    } catch (RemoteException e) {
+                        Slog.w(TAG, "Error authenticating dataset: " + e);
+                    }
+                }
+            }
+        }
+
+        void dumpLocked(String prefix, PrintWriter pw) {
+            pw.print(prefix); pw.print("mId: "); pw.println(mId);
+            pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken.get());
+            pw.print(prefix); pw.print("mCurrentAutoFillId: "); pw.println(mCurrentAutoFillId);
+            pw.print(prefix); pw.print("mCurrentBounds: "); pw.println(mCurrentBounds);
+            pw.print(prefix); pw.print("mCurrentResponse: "); pw.println(mCurrentResponse);
+            pw.print(prefix);
+                pw.print("mResponseRequiringAuth: "); pw.println(mResponseRequiringAuth);
+            pw.print(prefix);
+                pw.print("mDatasetRequiringAuth: "); pw.println(mDatasetRequiringAuth);
+            pw.print(prefix); pw.print("mAutoFillDirectly: "); pw.println(mAutoFillDirectly);
+        }
+
+        private void autoFillAppLocked(Dataset dataset, boolean removeSelf) {
+            try {
+                if (DEBUG) Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset);
+                mAppCallback.autoFill(dataset);
+
+                // TODO(b/33197203): temporarily hack: show the save notification after autofilled,
+                // since save is not automatically detected yet.
+                mUi.showSaveNotification(mUserId, mId); removeSelf = false;
+
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Error auto-filling activity: " + e);
+            }
+            if (removeSelf) {
+                removeSelf();
+            }
+        }
+
+        private void scanFingerprint(long opId) {
             // TODO(b/33197203): add MetricsLogger call
-            if (DEBUG) Slog.d(TAG, "showSaved(): " + Arrays.toString(ids));
+            if (DEBUG) Slog.d(TAG, "Starting fingerprint scan for op id: " + opId);
 
-            mUi.highlightSavedFields(ids);
-
-            removeSelf();
+            // TODO(b/33197203): since we're clearing the AutoFillService's identity, make sure
+            // this method is only called at the proper times, otherwise a malicious provider could
+            // keep the callback refence to bypass the check
+            final long token = Binder.clearCallingIdentity();
+            try {
+                // TODO(b/33197203): set a timeout?
+                mFingerprintService.authenticate(mAuthToken, opId, mUserId, mServiceReceiver, 0,
+                        null);
+            } catch (RemoteException e) {
+                // Local call, shouldn't happen.
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
         }
 
         private void removeSelf() {
             synchronized (mLock) {
-                removeServerCallbackLocked(id);
+                removeSessionLocked(mId);
             }
         }
     }
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
index 26f2451..4998e3f 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillManagerServiceShellCommand.java
@@ -74,7 +74,7 @@
 
     private int requestAutoFill(int flags) throws RemoteException {
         final int userId = getUserIdFromArgs();
-        mService.requestAutoFill(null, userId, null, flags);
+        mService.requestAutoFillForUser(userId, flags);
         return 0;
     }
 
diff --git a/services/autofill/java/com/android/server/autofill/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/AutoFillUI.java
index 6fafd5d..511d3d9 100644
--- a/services/autofill/java/com/android/server/autofill/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/AutoFillUI.java
@@ -15,36 +15,38 @@
  */
 package com.android.server.autofill;
 
-import static android.view.View.AUTO_FILL_FLAG_TYPE_SAVE;
 
-import static com.android.server.autofill.AutoFillManagerService.DEBUG;
+import static com.android.server.autofill.Helper.DEBUG;
 
 import android.app.Activity;
 import android.app.Notification;
 import android.app.Notification.Action;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.app.StatusBarManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.graphics.Rect;
+import android.graphics.PixelFormat;
 import android.os.Binder;
 import android.os.Bundle;
-import android.service.autofill.AutoFillService;
-import android.util.Log;
 import android.util.Slog;
 import android.view.autofill.AutoFillId;
 import android.view.autofill.Dataset;
 import android.view.autofill.FillResponse;
+import android.view.Gravity;
+import android.view.View;
+import android.view.WindowManager;
 import android.widget.Toast;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.UiThread;
 
+import java.io.PrintWriter;
 import java.util.Arrays;
 import java.util.List;
-import java.util.Objects;
-import java.util.Set;
 
 /**
  * Handles all auto-fill related UI tasks.
@@ -56,8 +58,16 @@
 
     private final Context mContext;
 
+    private final WindowManager mWm;
+
+    /**
+     * Custom snackbar UI used for saving autofill or other informational messages.
+     */
+    private View mSnackbar;
+
     AutoFillUI(Context context, AutoFillManagerService service, Object lock) {
         mContext = context;
+        mWm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
         mService = service;
         mLock = lock;
 
@@ -67,7 +77,7 @@
     /**
      * Displays an error message to the user.
      */
-    void showError(String message) {
+    void showError(CharSequence message) {
         // TODO(b/33197203): proper implementation
         UiThread.getHandler().runWithScissors(() -> {
             Toast.makeText(mContext, "AutoFill error: " + message, Toast.LENGTH_LONG).show();
@@ -87,12 +97,157 @@
 
     /**
      * Shows the options from a {@link FillResponse} so the user can pick up the proper
-     * {@link Dataset} (when the response has one).
+     * {@link Dataset} (when the response has one) for a given view (identified by
+     * {@code autoFillId}).
      */
-    void showOptions(int userId, int callbackId, FillResponse response) {
+    void showResponse(int userId, int sessionId, AutoFillId autoFillId, Rect bounds,
+            FillResponse response) {
+        if (DEBUG) Slog.d(TAG, "showResponse: id=" + autoFillId +  ", bounds=" + bounds);
         // TODO(b/33197203): proper implementation
-        // TODO(b/33197203): make sure if removes the callback from cache
-        showOptionsNotification(userId, callbackId, response);
+        // TODO(b/33197203): make sure if removes the session from cache
+        showOptionsNotification(userId, sessionId, autoFillId, response);
+    }
+
+    /**
+     * Shows an UI affordance indicating that user action is required before a {@link FillResponse}
+     * can be used.
+     *
+     * <p>It typically replaces the auto-fill bar with a message saying "Press fingerprint or tap to
+     * autofill" or "Tap to autofill", depending on the value of {@code usesFingerprint}.
+     */
+    void showFillResponseAuthenticationRequest(int userId, int sessionId, boolean usesFingerprint,
+            Bundle extras, int flags) {
+        // TODO(b/33197203): proper implementation
+        showAuthNotification(userId, sessionId, usesFingerprint, extras, flags);
+    }
+
+    /**
+     * Shows an UI affordance asking indicating that user action is required before a
+     * {@link Dataset} can be used.
+     *
+     * <p>It typically replaces the auto-fill bar with a message saying "Press fingerprint to
+     * autofill".
+     */
+    void showDatasetFingerprintAuthenticationRequest(Dataset dataset) {
+        if (DEBUG) Slog.d(TAG, "showDatasetAuthenticationRequest(): dataset=" + dataset);
+
+        // TODO(b/33197203): proper implementation (either pop up a fingerprint dialog or replace
+        // the auto-fill bar with a new message.
+        UiThread.getHandler().runWithScissors(() -> {
+            Toast.makeText(mContext, "AutoFill: press fingerprint to unlock " + dataset.getName(),
+                    Toast.LENGTH_LONG).show();
+        }, 0);
+    }
+
+    /**
+     * Shows the UI asking the user to save for auto-fill.
+     */
+    void showSaveUI(int userId, int sessionId) {
+        showSnackbar(new SavePrompt(mContext, new SavePrompt.OnSaveListener() {
+            @Override
+            public void onSaveClick() {
+                hideSnackbar();
+                synchronized (mLock) {
+                    final AutoFillManagerServiceImpl service = getServiceLocked(userId);
+                    service.requestSaveLocked(sessionId);
+                }
+            }
+            @Override
+            public void onCancelClick() {
+                hideSnackbar();
+            }
+        }));
+    }
+
+    /**
+     * Called by service after the user user the fingerprint sensors to authenticate.
+     */
+    void dismissFingerprintRequest(int userId, boolean success) {
+        if (DEBUG) Slog.d(TAG, "dismissFingerprintRequest(): ok=" + success);
+
+        dismissAuthNotification(userId);
+
+        if (!success) {
+            // TODO(b/33197203): proper implementation (snack bar / i18n string)
+            UiThread.getHandler().runWithScissors(() -> {
+                Toast.makeText(mContext, "AutoFill: fingerprint failed", Toast.LENGTH_LONG).show();
+            }, 0);
+        }
+    }
+
+    void dump(PrintWriter pw) {
+        pw.println("AufoFill UI");
+        final String prefix = "  ";
+        pw.print(prefix); pw.print("sResultCode: "); pw.println(sResultCode);
+        pw.print(prefix); pw.print("mSnackBar: "); pw.println(mSnackbar);
+    }
+
+    private AutoFillManagerServiceImpl getServiceLocked(int userId) {
+        final AutoFillManagerServiceImpl service = mService.getServiceForUserLocked(userId);
+        if (service == null) {
+            Slog.w(TAG, "no auto-fill service for user " + userId);
+        }
+        return service;
+    }
+
+    private void onSaveRequested(int userId, int sessionId) {
+        // TODO(b/33197203): displays the snack bar, until save notification is refactored
+        showSaveUI(userId, sessionId);
+    }
+
+    private void onDatasetPicked(int userId, Dataset dataset, int sessionId) {
+        synchronized (mLock) {
+            final AutoFillManagerServiceImpl service = getServiceLocked(userId);
+            if (service == null) return;
+
+            service.autoFillApp(sessionId, dataset);
+        }
+    }
+
+    private void onSessionDone(int userId, int sessionId) {
+        synchronized (mLock) {
+            final AutoFillManagerServiceImpl service = getServiceLocked(userId);
+            if (service == null) return;
+
+            service.removeSessionLocked(sessionId);
+        }
+    }
+
+    private void onResponseAuthenticationRequested(int userId, Bundle extras, int flags) {
+        synchronized (mLock) {
+            final AutoFillManagerServiceImpl service = getServiceLocked(userId);
+            if (service == null) return;
+
+            service.notifyResponseAuthenticationResult(extras, flags);
+        }
+    }
+
+    //similar to a snackbar, but can be a bit custom since it is more than just text. This will
+    //allow two buttons for saving or not saving the autofill for instance as well.
+    private void showSnackbar(View snackBar) {
+        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
+            WindowManager.LayoutParams.FILL_PARENT,
+            WindowManager.LayoutParams.WRAP_CONTENT,
+            WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, // TODO(b/33197203) use TYPE_AUTO_FILL
+            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN,
+            PixelFormat.TRANSLUCENT);
+
+        params.gravity = Gravity.BOTTOM | Gravity.LEFT;
+
+        UiThread.getHandler().runWithScissors(() -> {
+            mSnackbar = snackBar;
+            mWm.addView(mSnackbar, params);
+        }, 0);
+    }
+
+    private void hideSnackbar() {
+        UiThread.getHandler().runWithScissors(() -> {
+            if (mSnackbar != null) {
+                mWm.removeView(mSnackbar);
+                mSnackbar = null;
+            }
+        }, 0);
     }
 
     /////////////////////////////////////////////////////////////////////////////////
@@ -107,18 +262,21 @@
     // Extras used in the notification intents
     private static final String EXTRA_USER_ID = "user_id";
     private static final String EXTRA_NOTIFICATION_TYPE = "notification_type";
-    private static final String EXTRA_CALLBACK_ID = "callback_id";
+    private static final String EXTRA_SESSION_ID = "session_id";
     private static final String EXTRA_FILL_RESPONSE = "fill_response";
     private static final String EXTRA_DATASET = "dataset";
+    private static final String EXTRA_AUTH_REQUIRED_EXTRAS = "auth_required_extras";
+    private static final String EXTRA_FLAGS = "flags";
 
     private static final String TYPE_OPTIONS = "options";
-    private static final String TYPE_DELETE_CALLBACK = "delete_callback";
+    private static final String TYPE_FINISH_SESSION = "finish_session";
     private static final String TYPE_PICK_DATASET = "pick_dataset";
     private static final String TYPE_SAVE = "save";
+    private static final String TYPE_AUTH_RESPONSE = "auth_response";
 
-    @GuardedBy("mLock")
+    @GuardedBy("mServiceLock")
     private BroadcastReceiver mNotificationReceiver;
-    @GuardedBy("mLock")
+    @GuardedBy("mServiceLock")
     private final AutoFillManagerService mService;
     private final Object mLock;
 
@@ -139,68 +297,43 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             final int userId = intent.getIntExtra(EXTRA_USER_ID, -1);
+            final int sessionId = intent.getIntExtra(EXTRA_SESSION_ID, -1);
+            final String type = intent.getStringExtra(EXTRA_NOTIFICATION_TYPE);
+            if (type == null) {
+                Slog.wtf(TAG, "No extra " + EXTRA_NOTIFICATION_TYPE + " on intent " + intent);
+                return;
+            }
+            final Dataset dataset = intent.getParcelableExtra(EXTRA_DATASET);
+            final int flags = intent.getIntExtra(EXTRA_FLAGS, 0);
 
+            if (DEBUG) Slog.d(TAG, "Notification received: type=" + type + ", userId=" + userId
+                    + ", sessionId=" + sessionId);
             synchronized (mLock) {
-                final AutoFillManagerServiceImpl service = mService.getServiceForUserLocked(userId);
-                if (service == null) {
-                    Slog.w(TAG, "no auto-fill service for user " + userId);
-                    return;
-                }
-
-                final int callbackId = intent.getIntExtra(EXTRA_CALLBACK_ID, -1);
-                final String type = intent.getStringExtra(EXTRA_NOTIFICATION_TYPE);
-                if (type == null) {
-                    Slog.wtf(TAG, "No extra " + EXTRA_NOTIFICATION_TYPE + " on intent " + intent);
-                    return;
-                }
-                final FillResponse fillData = intent.getParcelableExtra(EXTRA_FILL_RESPONSE);
-                final Dataset dataset = intent.getParcelableExtra(EXTRA_DATASET);
-                final Bundle datasetArgs = dataset == null ? null : dataset.getExtras();
-                final Bundle fillDataArgs = fillData == null ? null : fillData.getExtras();
-
-                // Bundle sent on AutoFillService methods - only set if service provided a bundle
-                final Bundle extras = (datasetArgs == null && fillDataArgs == null)
-                        ? null : new Bundle();
-
-                if (DEBUG) Slog.d(TAG, "Notification received: type=" + type + ", userId=" + userId
-                        + ", callbackId=" + callbackId);
                 switch (type) {
                     case TYPE_SAVE:
-                        if (datasetArgs != null) {
-                            if (DEBUG) Log.d(TAG, "filldata args on save notificataion: " +
-                                    bundleToString(fillDataArgs));
-                            extras.putBundle(AutoFillService.EXTRA_RESPONSE_EXTRAS, fillDataArgs);
-                        }
-                        if (dataset != null) {
-                            if (DEBUG) Log.d(TAG, "dataset args on save notificataion: " +
-                                    bundleToString(datasetArgs));
-                            extras.putBundle(AutoFillService.EXTRA_DATASET_EXTRAS, datasetArgs);
-                        }
-                        service.requestAutoFill(null, extras, AUTO_FILL_FLAG_TYPE_SAVE);
+                        onSaveRequested(userId, sessionId);
                         break;
-                    case TYPE_DELETE_CALLBACK:
-                        service.removeServerCallbackLocked(callbackId);
+                    case TYPE_FINISH_SESSION:
+                        onSessionDone(userId, sessionId);
                         break;
                     case TYPE_PICK_DATASET:
-                        service.autoFillApp(callbackId, dataset);
+                        onDatasetPicked(userId, dataset, sessionId);
+
                         // Must cancel notification because it might be comming from action
-                        if (DEBUG) Log.d(TAG, "Cancelling notification");
+                        if (DEBUG) Slog.d(TAG, "Cancelling notification");
                         NotificationManager.from(mContext).cancel(TYPE_OPTIONS, userId);
 
-                        if (datasetArgs != null) {
-                            if (DEBUG) Log.d(TAG, "adding dataset's extra_data on save intent: "
-                                    + bundleToString(datasetArgs));
-                            extras.putBundle(AutoFillService.EXTRA_DATASET_EXTRAS, datasetArgs);
-                        }
-
-                        // Also show notification with option to save the data
-                        showSaveNotification(userId, fillData, dataset);
+                        break;
+                    case TYPE_AUTH_RESPONSE:
+                        onResponseAuthenticationRequested(userId,
+                                intent.getBundleExtra(EXTRA_AUTH_REQUIRED_EXTRAS), flags);
                         break;
                     default: {
                         Slog.w(TAG, "Unknown notification type: " + type);
                     }
                 }
             }
+            collapseStatusBar();
         }
     }
 
@@ -211,66 +344,46 @@
         return intent;
     }
 
-    private PendingIntent newPickDatasetPI(int userId, int callbackId, FillResponse response,
+    private PendingIntent newPickDatasetPI(int userId, int sessionId, FillResponse response,
             Dataset dataset) {
         final int resultCode = ++ sResultCode;
-        if (DEBUG) Log.d(TAG, "newPickDatasetPI: userId=" + userId + ", callback=" + callbackId
+        if (DEBUG) Slog.d(TAG, "newPickDatasetPI: userId=" + userId + ", sessionId=" + sessionId
                 + ", resultCode=" + resultCode);
 
         final Intent intent = newNotificationIntent(userId, TYPE_PICK_DATASET);
-        intent.putExtra(EXTRA_CALLBACK_ID, callbackId);
+        intent.putExtra(EXTRA_SESSION_ID, sessionId);
         intent.putExtra(EXTRA_FILL_RESPONSE, response);
         intent.putExtra(EXTRA_DATASET, dataset);
         return PendingIntent.getBroadcast(mContext, resultCode, intent,
                 PendingIntent.FLAG_ONE_SHOT);
     }
 
-    private static String bundleToString(Bundle bundle) {
-        if (bundle == null) {
-            return "null";
-        }
-        final Set<String> keySet = bundle.keySet();
-        final StringBuilder builder = new StringBuilder("[Bundle with ").append(keySet.size())
-                .append(" keys:");
-        for (String key : keySet) {
-            final Object value = bundle.get(key);
-            builder.append(' ').append(key).append('=');
-            builder.append((value instanceof Object[])
-                    ? Arrays.toString((Objects[]) value) : value);
-        }
-        return builder.append(']').toString();
-    }
-
     /**
      * Shows a notification with the results of an auto-fill request, using notications actions
      * to emulate the auto-fill bar buttons displaying the dataset names.
      */
-    private void showOptionsNotification(int userId, int callbackId, FillResponse response) {
+    private void showOptionsNotification(int userId, int callbackId, AutoFillId autoFillId,
+            FillResponse response) {
         final long token = Binder.clearCallingIdentity();
         try {
-            showOptionsNotificationAsSystem(userId, callbackId, response);
+            showOptionsNotificationAsSystem(userId, callbackId, autoFillId, response);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
     }
 
-    private void showOptionsNotificationAsSystem(int userId, int callbackId,
-            FillResponse response) {
+    private void showOptionsNotificationAsSystem(int userId, int sessionId,
+            AutoFillId autoFillId, FillResponse response) {
         // Make sure server callback is removed from cache if user cancels the notification.
-        final Intent deleteIntent = newNotificationIntent(userId, TYPE_DELETE_CALLBACK);
-        deleteIntent.putExtra(EXTRA_CALLBACK_ID, callbackId);
+        final Intent deleteIntent = newNotificationIntent(userId, TYPE_FINISH_SESSION)
+                .putExtra(EXTRA_SESSION_ID, sessionId);
         final PendingIntent deletePendingIntent = PendingIntent.getBroadcast(mContext,
                 ++sResultCode, deleteIntent, PendingIntent.FLAG_ONE_SHOT);
 
         final String title = "AutoFill Options";
 
-        final Notification.Builder notification = new Notification.Builder(mContext)
-                .setCategory(Notification.CATEGORY_SYSTEM)
+        final Notification.Builder notification = newNotificationBuilder()
                 .setOngoing(false)
-                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
-                .setLocalOnly(true)
-                .setColor(mContext.getColor(
-                        com.android.internal.R.color.system_notification_accent_color))
                 .setDeleteIntent(deletePendingIntent)
                 .setContentTitle(title);
 
@@ -287,13 +400,13 @@
         }
         boolean showSave = false;
         if (datasets == null ) {
-            subTitle = "No options to auto-fill this activity.";
+            subTitle = "No options to auto-fill " + autoFillId;
         } else if (datasets.isEmpty()) {
             if (savableIds.length == 0) {
-                subTitle = "No options to auto-fill this activity.";
+                subTitle = "No options to auto-fill " + autoFillId;
             } else {
-                subTitle = "No options to auto-fill this activity, but provider can save ids:\n"
-                        + Arrays.toString(savableIds);
+                subTitle = "No options to auto-fill " + autoFillId
+                        + ", but provider can save ids:\n" + Arrays.toString(savableIds);
                 showSave = true;
             }
         } else {
@@ -304,11 +417,20 @@
             } else {
                 autoCancel = false;
                 final int size = datasets.size();
-                subTitle = "There are " + size + " option(s).\n"
-                        + "Use the notification action(s) to select the proper one.";
+                subTitle = "There are " + size + " option(s) to fill " + autoFillId + ".\n"
+                        + "Use the notification action(s) to select the proper one."
+                        + "Actions with (F) require fingerprint unlock, and with (P) require"
+                        + "provider authentication to unlock";
                 for (Dataset dataset : datasets) {
-                    final CharSequence name = dataset.getName();
-                    final PendingIntent pi = newPickDatasetPI(userId, callbackId, response, dataset);
+                    final StringBuilder name = new StringBuilder(dataset.getName());
+                    if (dataset.isAuthRequired()) {
+                        if (dataset.hasCryptoObject()) {
+                            name.append("(F)");
+                        } else {
+                            name.append("(P)");
+                        }
+                    }
+                    final PendingIntent pi = newPickDatasetPI(userId, sessionId, response, dataset);
                     notification.addAction(new Action.Builder(null, name, pi).build());
                 }
             }
@@ -320,31 +442,32 @@
         NotificationManager.from(mContext).notify(TYPE_OPTIONS, userId, notification.build());
 
         if (showSave) {
-            showSaveNotification(userId, response, null);
+            showSaveNotification(userId, sessionId);
         }
     }
 
-    private void showSaveNotification(int userId, FillResponse response, Dataset dataset) {
-        final Intent saveIntent = newNotificationIntent(userId, TYPE_SAVE);
-        saveIntent.putExtra(EXTRA_FILL_RESPONSE, response);
-        if (dataset != null) {
-            saveIntent.putExtra(EXTRA_DATASET, dataset);
+    void showSaveNotification(int userId, int sessionId) {
+        final long token = Binder.clearCallingIdentity();
+        try {
+            showSaveNotificationAsSystem(userId, sessionId);
+        } finally {
+            Binder.restoreCallingIdentity(token);
         }
+    }
+
+    private void showSaveNotificationAsSystem(int userId, int sessionId) {
+        final Intent saveIntent = newNotificationIntent(userId, TYPE_SAVE)
+                .putExtra(EXTRA_SESSION_ID, sessionId);
+
         final PendingIntent savePendingIntent = PendingIntent.getBroadcast(mContext,
                 ++sResultCode, saveIntent, PendingIntent.FLAG_ONE_SHOT);
 
-        final String title = "AutoFill Save";
-        final String subTitle = "Tap notification to ask provider to save fields: \n"
-                + Arrays.toString(response.getSavableIds());
+        final String title = "AutoFill Save Emulation";
+        final String subTitle = "Tap notification to launch the save snackbar.";
 
-        final Notification notification = new Notification.Builder(mContext)
-                .setCategory(Notification.CATEGORY_SYSTEM)
+        final Notification notification = newNotificationBuilder()
                 .setAutoCancel(true)
                 .setOngoing(false)
-                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
-                .setLocalOnly(true)
-                .setColor(mContext.getColor(
-                        com.android.internal.R.color.system_notification_accent_color))
                 .setContentTitle(title)
                 .setContentIntent(savePendingIntent)
                 .setStyle(new Notification.BigTextStyle().bigText(subTitle))
@@ -352,6 +475,68 @@
         NotificationManager.from(mContext).notify(TYPE_SAVE, userId, notification);
     }
 
+    private void showAuthNotification(int userId, int sessionId, boolean usesFingerprint,
+            Bundle extras, int flags) {
+        final long token = Binder.clearCallingIdentity();
+        try {
+            showAuthNotificationAsSystem(userId, sessionId, usesFingerprint, extras, flags);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    private void showAuthNotificationAsSystem(int userId, int sessionId,
+            boolean usesFingerprint, Bundle extras, int flags) {
+        final String title = "AutoFill Authentication";
+        final StringBuilder subTitle = new StringBuilder("Provider require user authentication.\n");
+
+        final Intent authIntent = newNotificationIntent(userId, TYPE_AUTH_RESPONSE)
+                .putExtra(EXTRA_SESSION_ID, sessionId);
+        if (extras != null) {
+            authIntent.putExtra(EXTRA_AUTH_REQUIRED_EXTRAS, extras);
+        }
+        if (flags != 0) {
+            authIntent.putExtra(EXTRA_FLAGS, flags);
+        }
+        final PendingIntent authPendingIntent = PendingIntent.getBroadcast(mContext, ++sResultCode,
+                authIntent, PendingIntent.FLAG_ONE_SHOT);
+
+        if (usesFingerprint) {
+            subTitle.append("But kindly accepts your fingerprint instead"
+                    + "\n(tap fingerprint sensor to trigger it)");
+
+        } else {
+            subTitle.append("Tap notification to launch its authentication UI.");
+        }
+
+        final Notification.Builder notification = newNotificationBuilder()
+                .setAutoCancel(true)
+                .setOngoing(false)
+                .setContentTitle(title)
+                .setStyle(new Notification.BigTextStyle().bigText(subTitle.toString()));
+        if (authPendingIntent != null) {
+            notification.setContentIntent(authPendingIntent);
+        }
+        NotificationManager.from(mContext).notify(TYPE_AUTH_RESPONSE, userId, notification.build());
+    }
+
+    private void dismissAuthNotification(int userId) {
+        NotificationManager.from(mContext).cancel(TYPE_AUTH_RESPONSE, userId);
+    }
+
+    private Notification.Builder newNotificationBuilder() {
+        return new Notification.Builder(mContext)
+                .setCategory(Notification.CATEGORY_SYSTEM)
+                .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+                .setLocalOnly(true)
+                .setColor(mContext.getColor(
+                        com.android.internal.R.color.system_notification_accent_color));
+    }
+
+    private void collapseStatusBar() {
+        final StatusBarManager sbm = (StatusBarManager) mContext.getSystemService("statusbar");
+        sbm.collapsePanels();
+    }
     /////////////////////////////////////////
     // End of temporary notification code. //
     /////////////////////////////////////////
diff --git a/services/autofill/java/com/android/server/autofill/DatasetPicker.java b/services/autofill/java/com/android/server/autofill/DatasetPicker.java
new file mode 100644
index 0000000..bb64178
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/DatasetPicker.java
@@ -0,0 +1,139 @@
+/*
+ * 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.server.autofill;
+
+import static com.android.server.autofill.Helper.DEBUG;
+
+import android.app.Activity;
+import android.content.Context;
+import android.util.Slog;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.autofill.Dataset;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import java.util.List;
+
+/**
+ * View responsible for drawing the {@link Dataset} options that can be used to auto-fill an
+ * {@link Activity}.
+ */
+final class DatasetPicker extends LinearLayout {
+
+    private static final String TAG = "DatasetPicker";
+
+    // TODO(b/33197203): use / calculate proper values instead of hardcoding them
+    private static final LayoutParams NAME_PARAMS = new LayoutParams(400,
+            WindowManager.LayoutParams.WRAP_CONTENT);
+    private static final LayoutParams DROP_DOWN_PARAMS = new LayoutParams(100,
+            WindowManager.LayoutParams.WRAP_CONTENT);
+
+    private final Line[] mLines;
+
+    private boolean mExpanded;
+    private final Listener mListener;
+
+    public DatasetPicker(Context context, Listener listener, List<Dataset> datasets) {
+        super(context);
+
+        mListener = listener;
+
+        // TODO(b/33197203): use XML layout
+        setOrientation(LinearLayout.VERTICAL);
+
+        final int size = datasets.size();
+        mLines = new Line[size];
+
+        for (int i = 0; i < size; i++) {
+            final boolean first = i == 0;
+            final Line line = new Line(context, datasets.get(i), first);
+            mLines[i] = line;
+            if (first) {
+                addView(line);
+            }
+        }
+        mExpanded = false;
+    }
+
+    private void togleDropDown() {
+        if (mExpanded) {
+            hideDropDown();
+            return;
+        }
+        for (int i = 1; i < mLines.length; i++) {
+            addView(mLines[i]);
+        }
+        mExpanded = true;
+    }
+
+    private void hideDropDown() {
+        if (!mExpanded) return;
+        // TODO(b/33197203): invert order to be less janky?
+        for (int i = 1; i < mLines.length; i++) {
+            removeView(mLines[i]);
+        }
+        mExpanded = false;
+    }
+
+    private class Line extends LinearLayout {
+        final TextView name;
+        final ImageView dropDown;
+
+        private Line(Context context, Dataset dataset, boolean first) {
+            super(context);
+
+            final View.OnClickListener l = new View.OnClickListener() {
+
+                @Override
+                public void onClick(View v) {
+                    if (DEBUG) Slog.d(TAG, "dataset picked: " + dataset.getName());
+                    mListener.onDatasetPicked(dataset);
+
+                }
+            };
+
+            // TODO(b/33197203): use XML layout
+            setOrientation(LinearLayout.HORIZONTAL);
+
+            name = new TextView(context);
+            name.setLayoutParams(NAME_PARAMS);
+            name.setText(dataset.getName());
+            name.setOnClickListener(l);
+
+            dropDown = new ImageView(context);
+            dropDown.setLayoutParams(DROP_DOWN_PARAMS);
+            // TODO(b/33197203): use proper icon
+            dropDown.setImageResource(com.android.internal.R.drawable.arrow_down_float);
+            dropDown.setOnClickListener((v) -> {
+                togleDropDown();
+            });
+
+            if (!first) {
+                dropDown.setVisibility(View.INVISIBLE);
+            }
+
+            addView(name);
+            addView(dropDown);
+        }
+    }
+
+    static interface Listener {
+        void onDatasetPicked(Dataset dataset);
+    }
+}
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
new file mode 100644
index 0000000..79095a1
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -0,0 +1,57 @@
+/*
+ * 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.server.autofill;
+
+import android.os.Bundle;
+
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.Set;
+
+final class Helper {
+
+    static final boolean DEBUG = true; // TODO(b/33197203): set to false when stable
+    static final String REDACTED = "[REDACTED]";
+
+    static void append(StringBuilder builder, Bundle bundle) {
+        if (bundle == null) {
+            builder.append("N/A");
+        } else if (!DEBUG) {
+            builder.append(REDACTED);
+        } else {
+            final Set<String> keySet = bundle.keySet();
+            builder.append("[Bundle with ").append(keySet.size()).append(" extras:");
+            for (String key : keySet) {
+                final Object value = bundle.get(key);
+                builder.append(' ').append(key).append('=');
+                builder.append((value instanceof Object[])
+                        ? Arrays.toString((Objects[]) value) : value);
+            }
+            builder.append(']');
+        }
+    }
+
+    static String bundleToString(Bundle bundle) {
+        final StringBuilder builder = new StringBuilder();
+        append(builder, bundle);
+        return builder.toString();
+    }
+
+    private Helper() {
+        throw new UnsupportedOperationException("contains static members only");
+    }
+}
diff --git a/services/autofill/java/com/android/server/autofill/SavePrompt.java b/services/autofill/java/com/android/server/autofill/SavePrompt.java
new file mode 100644
index 0000000..f0b51e2
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/SavePrompt.java
@@ -0,0 +1,60 @@
+/*
+ * 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.server.autofill;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.widget.RelativeLayout;
+import android.widget.RelativeLayout.LayoutParams;
+import android.widget.TextView;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import com.android.internal.R;
+
+/**
+ * Autofill Save Prompt
+ */
+final class SavePrompt extends RelativeLayout {
+    public interface OnSaveListener {
+        void onSaveClick();
+        void onCancelClick();
+    }
+
+    private final TextView mNoButton;
+    private final TextView mYesButton;
+    private final OnSaveListener mListener;
+
+    SavePrompt(Context context, OnSaveListener listener) {
+        super(context);
+        mListener = listener;
+        LayoutInflater inflater = LayoutInflater.from(context);
+        View view = inflater.inflate(R.layout.autofill_save, this);
+
+        mNoButton = (TextView) view.findViewById(R.id.autofill_save_no);
+        mNoButton.setOnClickListener((v) -> {
+            mListener.onCancelClick();
+        });
+
+        mYesButton = (TextView) view.findViewById(R.id.autofill_save_yes);
+        mYesButton.setOnClickListener((v) -> {
+            mListener.onSaveClick();
+        });
+
+        //addView(view);
+    }
+}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 0e07ec0..b1560e6 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -275,7 +275,7 @@
                 } catch (IllegalArgumentException e) {
                     // Failed to parse the settings string, log this and move on
                     // with defaults.
-                    Slog.e(TAG, "Bad device idle settings", e);
+                    Slog.e(TAG, "Bad alarm manager settings", e);
                 }
 
                 MIN_FUTURITY = mParser.getLong(KEY_MIN_FUTURITY, DEFAULT_MIN_FUTURITY);
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 1f62945..dc0e3e1 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -41,6 +41,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.media.AudioAttributes;
 import android.os.AsyncTask;
 import android.os.Binder;
@@ -294,6 +295,25 @@
             }
         }
 
+        PackageManagerInternal packageManagerInternal = LocalServices.getService(
+                PackageManagerInternal.class);
+        packageManagerInternal.setExternalSourcesPolicy(
+                new PackageManagerInternal.ExternalSourcesPolicy() {
+                    @Override
+                    public int getPackageTrustedToInstallApps(String packageName, int uid) {
+                        int appOpMode = checkOperation(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES,
+                                uid, packageName);
+                        switch (appOpMode) {
+                            case AppOpsManager.MODE_ALLOWED:
+                                return PackageManagerInternal.ExternalSourcesPolicy.USER_TRUSTED;
+                            case AppOpsManager.MODE_ERRORED:
+                                return PackageManagerInternal.ExternalSourcesPolicy.USER_BLOCKED;
+                            default:
+                                return PackageManagerInternal.ExternalSourcesPolicy.USER_DEFAULT;
+                        }
+                    }
+                });
+
         StorageManagerInternal storageManagerInternal = LocalServices.getService(
                 StorageManagerInternal.class);
         storageManagerInternal.addExternalStoragePolicy(
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 822fc96..f315553 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -50,6 +50,7 @@
 import android.os.Process;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -59,6 +60,8 @@
 import android.provider.Settings.SettingNotFoundException;
 import android.util.Slog;
 
+import com.android.server.pm.PackageManagerService;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.concurrent.ConcurrentHashMap;
@@ -218,6 +221,11 @@
         @Override
         public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
                 Bundle prevRestrictions) {
+            if (!newRestrictions.containsKey(UserManager.DISALLOW_BLUETOOTH)
+                    && !prevRestrictions.containsKey(UserManager.DISALLOW_BLUETOOTH)) {
+                // The relevant restriction has not changed - do nothing.
+                return;
+            }
             final boolean bluetoothDisallowed =
                     newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH);
             if ((mEnable || mEnableExternal) && bluetoothDisallowed) {
@@ -228,6 +236,7 @@
                             e);
                 }
             }
+            updateOppLauncherComponentState(bluetoothDisallowed);
         }
     };
 
@@ -953,7 +962,13 @@
         UserManagerInternal userManagerInternal =
                 LocalServices.getService(UserManagerInternal.class);
         userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener);
-        if (isBluetoothDisallowed()) {
+        final boolean isBluetoothDisallowed = isBluetoothDisallowed();
+        PackageManagerService packageManagerService =
+                (PackageManagerService) ServiceManager.getService("package");
+        if (packageManagerService != null && !packageManagerService.isOnlyCoreApps()) {
+            updateOppLauncherComponentState(isBluetoothDisallowed);
+        }
+        if (isBluetoothDisallowed) {
             return;
         }
         if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
@@ -2011,6 +2026,28 @@
         }
     }
 
+    /**
+     * Disables BluetoothOppLauncherActivity component, so the Bluetooth sharing option is not
+     * offered to the user if Bluetooth is disallowed. Puts the component to its default state if
+     * Bluetooth is not disallowed.
+     *
+     * @param bluetoothDisallowed whether the {@link UserManager.DISALLOW_BLUETOOTH} user
+     * restriction was set.
+     */
+    private void updateOppLauncherComponentState(boolean bluetoothDisallowed) {
+        final ComponentName oppLauncherComponent = new ComponentName("com.android.bluetooth",
+                "com.android.bluetooth.opp.BluetoothOppLauncherActivity");
+        final int newState = bluetoothDisallowed
+                ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
+                : PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+        try {
+            mContext.getPackageManager()
+                    .setComponentEnabledSetting(oppLauncherComponent, newState, 0);
+        } catch (Exception e) {
+            // The component was not found, do nothing.
+        }
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index f3f8da8..1f8702a 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -690,11 +690,6 @@
     }
     private LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker();
 
-    @VisibleForTesting
-    protected HandlerThread createHandlerThread() {
-        return new HandlerThread("ConnectivityServiceThread");
-    }
-
     public ConnectivityService(Context context, INetworkManagementService netManager,
             INetworkStatsService statsService, INetworkPolicyManager policyManager) {
         this(context, netManager, statsService, policyManager, new IpConnectivityLog());
@@ -715,7 +710,7 @@
         mDefaultMobileDataRequest = createInternetRequestForTransport(
                 NetworkCapabilities.TRANSPORT_CELLULAR, NetworkRequest.Type.BACKGROUND_REQUEST);
 
-        mHandlerThread = createHandlerThread();
+        mHandlerThread = new HandlerThread("ConnectivityServiceThread");
         mHandlerThread.start();
         mHandler = new InternalHandler(mHandlerThread.getLooper());
         mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper());
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index bee1f97..c4666dc 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -926,7 +926,7 @@
             return;
         }
         final List<InputMethodInfo> suitableImes = InputMethodUtils.getDefaultEnabledImes(
-                context, mSystemReady, mSettings.getEnabledInputMethodListLocked());
+                context, mSettings.getEnabledInputMethodListLocked());
         if (suitableImes.isEmpty()) {
             Slog.i(TAG, "No default found");
             return;
@@ -3089,7 +3089,7 @@
 
         if (resetDefaultEnabledIme) {
             final ArrayList<InputMethodInfo> defaultEnabledIme =
-                    InputMethodUtils.getDefaultEnabledImes(mContext, mSystemReady, mMethodList);
+                    InputMethodUtils.getDefaultEnabledImes(mContext, mMethodList);
             final int N = defaultEnabledIme.size();
             for (int i = 0; i < N; ++i) {
                 final InputMethodInfo imi =  defaultEnabledIme.get(i);
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 6cc72de..4ab894f 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -132,6 +132,8 @@
     private static final String FUSED_LOCATION_SERVICE_ACTION =
             "com.android.location.service.FusedLocationProvider";
 
+    private static final String GMSCORE_PACKAGE = "com.android.google.gms";
+
     private static final int MSG_LOCATION_CHANGED = 1;
 
     private static final long NANOS_PER_MILLI = 1000000L;
@@ -140,7 +142,7 @@
     private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
 
     // default background throttling interval if not overriden in settings
-    private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 1000;
+    private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 10 * 60 * 1000;
 
     // Location Providers may sometimes deliver location updates
     // slightly faster that requested - provide grace period so
@@ -214,10 +216,13 @@
     private final HashMap<String, Location> mLastLocationCoarseInterval =
             new HashMap<>();
 
-    // all providers that operate over proxy, for authorizing incoming location
+    // all providers that operate over proxy, for authorizing incoming location and whitelisting
+    // throttling
     private final ArrayList<LocationProviderProxy> mProxyProviders =
             new ArrayList<>();
 
+    private String[] mBackgroundThrottlePackageWhitelist = new String[]{};
+
     // current active user on the device - other users are denied location data
     private int mCurrentUserId = UserHandle.USER_SYSTEM;
     private int[] mCurrentUserProfiles = new int[] { UserHandle.USER_SYSTEM };
@@ -359,6 +364,26 @@
                         }
                     }
                 }, UserHandle.USER_ALL);
+        mContext.getContentResolver().registerContentObserver(
+            Settings.Global.getUriFor(
+                Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
+            true,
+            new ContentObserver(mLocationHandler) {
+                @Override
+                public void onChange(boolean selfChange) {
+                    synchronized (mLock) {
+                        String setting = Settings.Global.getString(
+                            mContext.getContentResolver(),
+                            Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
+                        if (setting == null) {
+                            setting = "";
+                        }
+
+                        mBackgroundThrottlePackageWhitelist = setting.split(",");
+                        updateProvidersLocked();
+                    }
+                }
+            }, UserHandle.USER_ALL);
         mPackageMonitor.register(mContext, mLocationHandler.getLooper(), true);
 
         // listen for user change
@@ -1066,19 +1091,6 @@
         mProvidersByName.remove(provider.getName());
     }
 
-    private boolean isOverlayProviderPackageLocked(String packageName) {
-        for (LocationProviderInterface provider : mProviders) {
-            if (provider instanceof LocationProviderProxy) {
-                if (packageName.equals(
-                        ((LocationProviderProxy) provider).getConnectedPackageName())) {
-                    return true;
-                }
-            }
-        }
-
-        return false;
-    }
-
     /**
      * Returns "true" if access to the specified location provider is allowed by the current
      * user's settings. Access to all location providers is forbidden to non-location-provider
@@ -1542,8 +1554,28 @@
         p.setRequest(providerRequest, worksource);
     }
 
-    private boolean isThrottlingExemptLocked(Receiver recevier) {
-        return isOverlayProviderPackageLocked(recevier.mPackageName);
+    private boolean isThrottlingExemptLocked(Receiver receiver) {
+        if (receiver.mUid == Process.SYSTEM_UID) {
+            return true;
+        }
+
+        if (receiver.mPackageName.equals(GMSCORE_PACKAGE)) {
+            return true;
+        }
+
+        for (LocationProviderProxy provider : mProxyProviders) {
+            if (receiver.mPackageName.equals(provider.getConnectedPackageName())) {
+                return true;
+            }
+        }
+
+        for (String whitelistedPackage : mBackgroundThrottlePackageWhitelist) {
+            if (receiver.mPackageName.equals(whitelistedPackage)) {
+                return true;
+            }
+        }
+
+        return false;
     }
 
     private class UpdateRecord {
@@ -1766,7 +1798,7 @@
         if (D) Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
                 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
                 + (record.mIsForegroundUid ? "foreground" : "background")
-                + (isOverlayProviderPackageLocked(receiver.mPackageName) ? " [whitelisted]" : "") + ")");
+                + (isThrottlingExemptLocked(receiver) ? " [whitelisted]" : "") + ")");
 
         UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
         if (oldRecord != null) {
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index dab4dfb..25016f6 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -60,6 +60,7 @@
 import android.provider.Settings;
 import android.provider.Settings.Global;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.Pair;
 import android.util.TimedRemoteCaller;
@@ -77,12 +78,13 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.BiConsumer;
-import java.util.function.Function;
 import java.util.function.Supplier;
+import java.util.function.UnaryOperator;
 
 /**
  * Backing service for {@link android.net.NetworkScoreManager}.
@@ -91,6 +93,7 @@
 public class NetworkScoreService extends INetworkScoreService.Stub {
     private static final String TAG = "NetworkScoreService";
     private static final boolean DBG = Build.IS_DEBUGGABLE && Log.isLoggable(TAG, Log.DEBUG);
+    private static final boolean VERBOSE = Build.IS_DEBUGGABLE && Log.isLoggable(TAG, Log.VERBOSE);
 
     private final Context mContext;
     private final NetworkScorerAppManager mNetworkScorerAppManager;
@@ -407,7 +410,7 @@
                 }
 
                 final BiConsumer<INetworkScoreCache, Object> consumer =
-                        new FilteringCacheUpdatingConsumer(mContext, entry.getValue(),
+                        FilteringCacheUpdatingConsumer.create(mContext, entry.getValue(),
                                 entry.getKey());
                 sendCacheUpdateCallback(consumer, Collections.singleton(callbackList));
             }
@@ -424,25 +427,28 @@
      * accepted {@link INetworkScoreCache} implementation.
      */
     @VisibleForTesting
-    public static class FilteringCacheUpdatingConsumer
+    static class FilteringCacheUpdatingConsumer
             implements BiConsumer<INetworkScoreCache, Object> {
         private final Context mContext;
         private final List<ScoredNetwork> mScoredNetworkList;
         private final int mNetworkType;
-        // TODO(jjoslin): 1/23/17 - Consider a Map if we implement more filters.
-        private Function<List<ScoredNetwork>, List<ScoredNetwork>> mCurrentNetworkFilter;
-        private Function<List<ScoredNetwork>, List<ScoredNetwork>> mScanResultsFilter;
+        // TODO: 1/23/17 - Consider a Map if we implement more filters.
+        // These are created on-demand to defer the construction cost until
+        // an instance is actually needed.
+        private UnaryOperator<List<ScoredNetwork>> mCurrentNetworkFilter;
+        private UnaryOperator<List<ScoredNetwork>> mScanResultsFilter;
 
-        public FilteringCacheUpdatingConsumer(Context context,
+        static FilteringCacheUpdatingConsumer create(Context context,
                 List<ScoredNetwork> scoredNetworkList, int networkType) {
-            this(context, scoredNetworkList, networkType, null, null);
+            return new FilteringCacheUpdatingConsumer(context, scoredNetworkList, networkType,
+                    null, null);
         }
 
         @VisibleForTesting
-        public FilteringCacheUpdatingConsumer(Context context,
+        FilteringCacheUpdatingConsumer(Context context,
                 List<ScoredNetwork> scoredNetworkList, int networkType,
-                Function<List<ScoredNetwork>, List<ScoredNetwork>> currentNetworkFilter,
-                Function<List<ScoredNetwork>, List<ScoredNetwork>> scanResultsFilter) {
+                UnaryOperator<List<ScoredNetwork>> currentNetworkFilter,
+                UnaryOperator<List<ScoredNetwork>> scanResultsFilter) {
             mContext = context;
             mScoredNetworkList = scoredNetworkList;
             mNetworkType = networkType;
@@ -461,11 +467,10 @@
                 final List<ScoredNetwork> filteredNetworkList =
                         filterScores(mScoredNetworkList, filterType);
                 if (!filteredNetworkList.isEmpty()) {
-                    networkScoreCache.updateScores(
-                            Collections.unmodifiableList(filteredNetworkList));
+                    networkScoreCache.updateScores(filteredNetworkList);
                 }
             } catch (RemoteException e) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
+                if (VERBOSE) {
                     Log.v(TAG, "Unable to update scores of type " + mNetworkType, e);
                 }
             }
@@ -554,10 +559,8 @@
      *       the computation is only done once.
      */
     @VisibleForTesting
-    public static class CurrentNetworkScoreCacheFilter
-            implements Function<List<ScoredNetwork>, List<ScoredNetwork>> {
+    static class CurrentNetworkScoreCacheFilter implements UnaryOperator<List<ScoredNetwork>> {
         private final NetworkKey mCurrentNetwork;
-        private Pair<List<ScoredNetwork>, Integer> mCache;
 
         CurrentNetworkScoreCacheFilter(Supplier<WifiInfo> wifiInfoSupplier) {
             mCurrentNetwork = NetworkKey.createFromWifiInfo(wifiInfoSupplier.get());
@@ -569,25 +572,14 @@
                 return Collections.emptyList();
             }
 
-            final int inputListHash = scoredNetworks.hashCode();
-            if (mCache == null || mCache.second != inputListHash) {
-                ScoredNetwork currentScore = null;
-                for (int i = 0; i < scoredNetworks.size(); i++) {
-                    final ScoredNetwork scoredNetwork = scoredNetworks.get(i);
-                    if (scoredNetwork.networkKey.equals(mCurrentNetwork)) {
-                        currentScore = scoredNetwork;
-                        break;
-                    }
-                }
-
-                if (currentScore == null) {
-                    mCache = Pair.create(Collections.emptyList(), inputListHash);
-                } else {
-                    mCache = Pair.create(Collections.singletonList(currentScore), inputListHash);
+            for (int i = 0; i < scoredNetworks.size(); i++) {
+                final ScoredNetwork scoredNetwork = scoredNetworks.get(i);
+                if (scoredNetwork.networkKey.equals(mCurrentNetwork)) {
+                    return Collections.singletonList(scoredNetwork);
                 }
             }
 
-            return mCache.first;
+            return Collections.emptyList();
         }
     }
 
@@ -602,15 +594,14 @@
      *       times in a row the computation is only done once.
      */
     @VisibleForTesting
-    public static class ScanResultsScoreCacheFilter
-            implements Function<List<ScoredNetwork>, List<ScoredNetwork>> {
-        private final List<NetworkKey> mScanResultKeys;
-        private Pair<List<ScoredNetwork>, Integer> mCache;
+    static class ScanResultsScoreCacheFilter implements UnaryOperator<List<ScoredNetwork>> {
+        private final Set<NetworkKey> mScanResultKeys;
 
         ScanResultsScoreCacheFilter(Supplier<List<ScanResult>> resultsSupplier) {
-            mScanResultKeys = new ArrayList<>();
             List<ScanResult> scanResults = resultsSupplier.get();
-            for (int i = 0; i < scanResults.size(); i++) {
+            final int size = scanResults.size();
+            mScanResultKeys = new ArraySet<>(size);
+            for (int i = 0; i < size; i++) {
                 ScanResult scanResult = scanResults.get(i);
                 mScanResultKeys.add(NetworkKey.createFromScanResult(scanResult));
             }
@@ -622,22 +613,15 @@
                 return Collections.emptyList();
             }
 
-            final int inputListHash = scoredNetworks.hashCode();
-            if (mCache == null || mCache.second != inputListHash) {
-                List<ScoredNetwork> filteredScores = new ArrayList<>();
-                for (int i = 0; i < scoredNetworks.size(); i++) {
-                    final ScoredNetwork scoredNetwork = scoredNetworks.get(i);
-                    for (int j = 0; j < mScanResultKeys.size(); j++) {
-                        final NetworkKey scanResultKey = mScanResultKeys.get(j);
-                        if (scanResultKey.equals(scoredNetwork.networkKey)) {
-                            filteredScores.add(scoredNetwork);
-                        }
-                    }
+            List<ScoredNetwork> filteredScores = new ArrayList<>();
+            for (int i = 0; i < scoredNetworks.size(); i++) {
+                final ScoredNetwork scoredNetwork = scoredNetworks.get(i);
+                if (mScanResultKeys.contains(scoredNetwork.networkKey)) {
+                    filteredScores.add(scoredNetwork);
                 }
-                mCache = Pair.create(filteredScores, inputListHash);
             }
 
-            return mCache.first;
+            return filteredScores;
         }
     }
 
@@ -796,7 +780,7 @@
                     return caller.getRecommendationResult(provider, request);
                 } catch (RemoteException | TimeoutException e) {
                     Log.w(TAG, "Failed to request a recommendation.", e);
-                    // TODO(jjoslin): 12/15/16 - Keep track of failures.
+                    // TODO: 12/15/16 - Keep track of failures.
                 }
             }
 
@@ -850,7 +834,7 @@
                     return;
                 } catch (RemoteException e) {
                     Log.w(TAG, "Failed to request a recommendation.", e);
-                    // TODO(jjoslin): 12/15/16 - Keep track of failures.
+                    // TODO: 12/15/16 - Keep track of failures.
                     // Remove the timeout message
                     mHandler.removeMessages(timeoutMsg.what, pair);
                     // Will fall through and send back the default recommendation.
@@ -873,12 +857,12 @@
             if (provider != null) {
                 try {
                     provider.requestScores(networks);
-                    // TODO(jjoslin): 12/15/16 - Consider pushing null scores into the cache to
+                    // TODO: 12/15/16 - Consider pushing null scores into the cache to
                     // prevent repeated requests for the same scores.
                     return true;
                 } catch (RemoteException e) {
                     Log.w(TAG, "Failed to request scores.", e);
-                    // TODO(jjoslin): 12/15/16 - Keep track of failures.
+                    // TODO: 12/15/16 - Keep track of failures.
                 }
             }
             return false;
@@ -890,32 +874,37 @@
     @Override
     protected void dump(final FileDescriptor fd, final PrintWriter writer, final String[] args) {
         mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG);
-        NetworkScorerAppData currentScorer = mNetworkScorerAppManager.getActiveScorer();
-        if (currentScorer == null) {
-            writer.println("Scoring is disabled.");
-            return;
-        }
-        writer.println("Current scorer: " + currentScorer.packageName);
+        final long token = Binder.clearCallingIdentity();
+        try {
+            NetworkScorerAppData currentScorer = mNetworkScorerAppManager.getActiveScorer();
+            if (currentScorer == null) {
+                writer.println("Scoring is disabled.");
+                return;
+            }
+            writer.println("Current scorer: " + currentScorer.packageName);
 
-        sendCacheUpdateCallback(new BiConsumer<INetworkScoreCache, Object>() {
-            @Override
-            public void accept(INetworkScoreCache networkScoreCache, Object cookie) {
-                try {
-                  TransferPipe.dumpAsync(networkScoreCache.asBinder(), fd, args);
-                } catch (IOException | RemoteException e) {
-                  writer.println("Failed to dump score cache: " + e);
+            sendCacheUpdateCallback(new BiConsumer<INetworkScoreCache, Object>() {
+                @Override
+                public void accept(INetworkScoreCache networkScoreCache, Object cookie) {
+                    try {
+                        TransferPipe.dumpAsync(networkScoreCache.asBinder(), fd, args);
+                    } catch (IOException | RemoteException e) {
+                        writer.println("Failed to dump score cache: " + e);
+                    }
+                }
+            }, getScoreCacheLists());
+
+            synchronized (mServiceConnectionLock) {
+                if (mServiceConnection != null) {
+                    mServiceConnection.dump(fd, writer, args);
+                } else {
+                    writer.println("ScoringServiceConnection: null");
                 }
             }
-        }, getScoreCacheLists());
-
-        synchronized (mServiceConnectionLock) {
-            if (mServiceConnection != null) {
-                mServiceConnection.dump(fd, writer, args);
-            } else {
-                writer.println("ScoringServiceConnection: null");
-            }
+            writer.flush();
+        } finally {
+            Binder.restoreCallingIdentity(token);
         }
-        writer.flush();
     }
 
     /**
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index d51e96a..c77a407 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -19,6 +19,8 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.UserInfo;
+import android.os.BatteryManager;
+import android.os.BatteryManagerInternal;
 import android.os.Build;
 import android.os.RecoverySystem;
 import android.os.SystemClock;
@@ -57,15 +59,31 @@
     private static final int LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS = 3;
     private static final int LEVEL_FACTORY_RESET = 4;
 
-    private static final boolean DISABLE_RESET_SETTINGS = true;
-
     /** Threshold for boot loops */
     private static final Threshold sBoot = new BootThreshold();
     /** Threshold for app crash loops */
     private static SparseArray<Threshold> sApps = new SparseArray<>();
 
     private static boolean isDisabled() {
-        return Build.IS_ENG || SystemProperties.getBoolean(PROP_DISABLE_RESCUE, false);
+        // We're disabled on all engineering devices
+        if (Build.IS_ENG) return true;
+
+        // We're disabled on userdebug devices connected over USB, since that's
+        // a decent signal that someone is actively trying to debug the device,
+        // or that it's in a lab environment.
+        if (Build.IS_USERDEBUG) {
+            try {
+                if (LocalServices.getService(BatteryManagerInternal.class)
+                        .getPlugType() == BatteryManager.BATTERY_PLUGGED_USB) {
+                    return true;
+                } else {
+                }
+            } catch (Throwable ignored) {
+            }
+        }
+
+        // One last-ditch check
+        return SystemProperties.getBoolean(PROP_DISABLE_RESCUE, false);
     }
 
     /**
@@ -161,8 +179,6 @@
     }
 
     private static void resetAllSettings(Context context, int mode) throws Exception {
-        if (DISABLE_RESET_SETTINGS) return;
-
         // Try our best to reset all settings possible, and once finished
         // rethrow any exception that we encountered
         Exception res = null;
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index e11dd1a..629da86 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -108,6 +108,8 @@
 import com.android.server.NativeDaemonConnector.SensitiveArg;
 import com.android.server.pm.PackageManagerService;
 import com.android.server.storage.AppFuseBridge;
+import com.android.server.storage.FileCollector;
+
 import libcore.io.IoUtils;
 import libcore.util.EmptyArray;
 
@@ -817,6 +819,9 @@
     }
 
     private void handleSystemReady() {
+        // Register kernel mapping from extensions to statistics GIDs
+        FileCollector.updateKernelExtensions();
+
         initIfReadyAndConnected();
         resetIfReadyAndConnected();
 
@@ -2080,9 +2085,6 @@
 
     @Override
     public String getPrimaryStorageUuid() {
-        enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
-        waitForReady();
-
         synchronized (mLock) {
             return mPrimaryStorageUuid;
         }
diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java
index cbd7be7..2b5166e 100644
--- a/services/core/java/com/android/server/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/TextServicesManagerService.java
@@ -198,7 +198,7 @@
                 mUserManager.getProfileIdsWithDisabled(mSettings.getCurrentUserId()));
     }
 
-    private class TextServicesMonitor extends PackageMonitor {
+    private final class TextServicesMonitor extends PackageMonitor {
         private boolean isChangingPackagesOfCurrentUser() {
             final int userId = getChangingUserId();
             final boolean retval = userId == mSettings.getCurrentUserId();
@@ -236,7 +236,7 @@
         }
     }
 
-    class TextServicesBroadcastReceiver extends BroadcastReceiver {
+    private final class TextServicesBroadcastReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
             final String action = intent.getAction();
@@ -618,8 +618,7 @@
             Slog.w(TAG, "Start spell checker session inner locked.");
         }
         final String sciId = info.getId();
-        final InternalServiceConnection connection = new InternalServiceConnection(
-                sciId, locale, bundle);
+        final InternalServiceConnection connection = new InternalServiceConnection(sciId);
         final Intent serviceIntent = new Intent(SpellCheckerService.SERVICE_INTERFACE);
         serviceIntent.setComponent(info.getComponent());
         if (DBG) {
@@ -836,7 +835,7 @@
     // SpellCheckerBindGroup contains active text service session listeners.
     // If there are no listeners anymore, the SpellCheckerBindGroup instance will be removed from
     // mSpellCheckerBindGroups
-    private class SpellCheckerBindGroup {
+    private final class SpellCheckerBindGroup {
         private final String TAG = SpellCheckerBindGroup.class.getSimpleName();
         private final InternalServiceConnection mInternalConnection;
         private final CopyOnWriteArrayList<InternalDeathRecipient> mListeners =
@@ -972,15 +971,10 @@
         }
     }
 
-    private class InternalServiceConnection implements ServiceConnection {
+    private final class InternalServiceConnection implements ServiceConnection {
         private final String mSciId;
-        private final String mLocale;
-        private final Bundle mBundle;
-        public InternalServiceConnection(
-                String id, String locale, Bundle bundle) {
+        public InternalServiceConnection(String id) {
             mSciId = id;
-            mLocale = locale;
-            mBundle = bundle;
         }
 
         @Override
@@ -1013,7 +1007,7 @@
         }
     }
 
-    private class InternalDeathRecipient implements IBinder.DeathRecipient {
+    private static final class InternalDeathRecipient implements IBinder.DeathRecipient {
         public final ITextServicesSessionListener mTsListener;
         public final ISpellCheckerSessionListener mScListener;
         public final String mScLocale;
@@ -1041,7 +1035,7 @@
         }
     }
 
-    private static class TextServicesSettings {
+    private static final class TextServicesSettings {
         private final ContentResolver mResolver;
         @UserIdInt
         private int mCurrentUserId;
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 0a6c62f..bfa3f04 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -63,8 +63,8 @@
 import android.content.pm.Signature;
 import android.content.pm.UserInfo;
 import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteStatement;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Environment;
@@ -76,6 +76,7 @@
 import android.os.Process;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
+import android.os.StrictMode;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -111,15 +112,16 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
-import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -174,17 +176,18 @@
     private static final String PRE_N_DATABASE_NAME = "accounts.db";
     private static final Intent ACCOUNTS_CHANGED_INTENT;
 
+    private static final int SIGNATURE_CHECK_MISMATCH = 0;
+    private static final int SIGNATURE_CHECK_MATCH = 1;
+    private static final int SIGNATURE_CHECK_UID_MATCH = 2;
+
     static {
         ACCOUNTS_CHANGED_INTENT = new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION);
         ACCOUNTS_CHANGED_INTENT.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
     }
 
-
     private final LinkedHashMap<String, Session> mSessions = new LinkedHashMap<String, Session>();
     private final AtomicInteger mNotificationIds = new AtomicInteger(1);
 
-    private static final String NEW_ACCOUNT_VISIBLE = "android.accounts.NEW_ACCOUNT_VISIBLE";
-
     static class UserAccounts {
         private final int userId;
         final AccountsDb accountsDb;
@@ -204,6 +207,11 @@
         /** protected by the {@link #cacheLock} */
         private final TokenCache accountTokenCaches = new TokenCache();
 
+        /** protected by the {@link #cacheLock} */
+        // TODO use callback to set up the map.
+        private final Map<String, LinkedHashSet<String>> mApplicationAccountRequestMappings =
+                new HashMap<>();
+
         /**
          * protected by the {@link #cacheLock}
          *
@@ -261,8 +269,6 @@
 
         sThis.set(this);
 
-        addRequestsForPreInstalledApplications();
-
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
         intentFilter.addDataScheme("package");
@@ -285,7 +291,7 @@
                         @Override
                         public void run() {
                             purgeOldGrantsAll();
-                            // TODO remove visibility entries.
+                            // Notify authenticator about removed app?
                         }
                     };
                     mHandler.post(purgingRunnable);
@@ -294,29 +300,6 @@
             }
         }, intentFilter);
 
-        IntentFilter packageAddedOrChangedFilter = new IntentFilter();
-        intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
-        packageAddedOrChangedFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
-        packageAddedOrChangedFilter.addDataScheme("package");
-        mContext.registerReceiverAsUser(new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context1, Intent intent) {
-                mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        int uidOfInstalledApplication =
-                                intent.getIntExtra(Intent.EXTRA_UID, -1);
-                        if(uidOfInstalledApplication != -1) {
-                            registerAccountTypesSupported(
-                                    uidOfInstalledApplication,
-                                    getUserAccounts(
-                                    UserHandle.getUserId(uidOfInstalledApplication)));
-                        }
-                    }
-                });
-            }
-        }, UserHandle.ALL, packageAddedOrChangedFilter, null, null);
-
         IntentFilter userFilter = new IntentFilter();
         userFilter.addAction(Intent.ACTION_USER_REMOVED);
         mContext.registerReceiverAsUser(new BroadcastReceiver() {
@@ -380,11 +363,13 @@
                 final long identity = Binder.clearCallingIdentity();
                 try {
                     for (String packageName : packageNames) {
-                        if (mPackageManager.checkPermission(
-                                Manifest.permission.GET_ACCOUNTS, packageName)
-                                        != PackageManager.PERMISSION_GRANTED) {
-                            continue;
-                        }
+                                // if app asked for permission we need to cancel notification even
+                                // for O+ applications.
+                                if (mPackageManager.checkPermission(
+                                        Manifest.permission.GET_ACCOUNTS,
+                                        packageName) != PackageManager.PERMISSION_GRANTED) {
+                                    continue;
+                                }
 
                         if (accounts == null) {
                             accounts = getAccountsAsUser(null, userId, "android");
@@ -443,112 +428,376 @@
     }
 
     @Override
-    public boolean addAccountExplicitlyWithVisibility(Account account, String password, Bundle extras,
-            Map uidToVisibility) {
-        // TODO implementation
-        return false;
+    public boolean addAccountExplicitlyWithVisibility(Account account, String password,
+            Bundle extras, Map uidToVisibility) {
+        Bundle.setDefusable(extras, true);
+
+        final int callingUid = Binder.getCallingUid();
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Log.v(TAG, "addAccountExplicitly: " + account + ", caller's uid " + callingUid
+                    + ", pid " + Binder.getCallingPid());
+        }
+        Preconditions.checkNotNull(account, "account cannot be null");
+        int userId = UserHandle.getCallingUserId();
+        if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
+            String msg = String.format("uid %s cannot explicitly add accounts of type: %s",
+                    callingUid, account.type);
+            throw new SecurityException(msg);
+        }
+        /*
+         * Child users are not allowed to add accounts. Only the accounts that are shared by the
+         * parent profile can be added to child profile.
+         *
+         * TODO: Only allow accounts that were shared to be added by a limited user.
+         */
+        // fails if the account already exists
+        long identityToken = clearCallingIdentity();
+        try {
+            UserAccounts accounts = getUserAccounts(userId);
+            return addAccountInternal(accounts, account, password, extras, callingUid,
+                    (Map<Integer, Integer>) uidToVisibility);
+        } finally {
+            restoreCallingIdentity(identityToken);
+        }
     }
 
     @Override
     public Map<Account, Integer> getAccountsAndVisibilityForPackage(String packageName,
             String accountType) {
-        // TODO Implement.
-        return new HashMap<Account, Integer>();
+        int callingUid = Binder.getCallingUid();
+        boolean isSystemUid = UserHandle.isSameApp(callingUid, Process.SYSTEM_UID);
+        List<String> managedTypes =
+                getTypesForCaller(callingUid, UserHandle.getUserId(callingUid), isSystemUid);
+
+        if ((accountType != null && !managedTypes.contains(accountType))
+                || (accountType == null && !isSystemUid)) {
+            throw new SecurityException(
+                    "getAccountsAndVisibilityForPackage() called from unauthorized uid "
+                            + callingUid + " with packageName=" + packageName);
+        }
+        if (accountType != null) {
+            managedTypes = new ArrayList<String>();
+            managedTypes.add(accountType);
+        }
+
+        return getAccountsAndVisibilityForPackage(packageName, managedTypes, callingUid,
+                getUserAccounts(UserHandle.getUserId(callingUid)));
+    }
+
+    /*
+     * accountTypes may not be null
+     */
+    private Map<Account, Integer> getAccountsAndVisibilityForPackage(String packageName,
+            List<String> accountTypes, Integer callingUid, UserAccounts accounts) {
+        int uid = 0;
+        try {
+            uid = mPackageManager.getPackageUidAsUser(packageName,
+                    UserHandle.getUserId(callingUid));
+        } catch (NameNotFoundException e) {
+            Log.d(TAG, "Package not found " + e.getMessage());
+            return new HashMap<>();
+        }
+
+        Map<Account, Integer> result = new HashMap<>();
+        for (String accountType : accountTypes) {
+            synchronized (accounts.cacheLock) {
+                final Account[] accountsOfType = accounts.accountCache.get(accountType);
+                if (accountsOfType != null) {
+                    for (Account account : accountsOfType) {
+                        result.put(account,
+                                resolveAccountVisibility(account, uid, packageName, accounts));
+                    }
+                }
+            }
+        }
+        return filterSharedAccounts(accounts, result, callingUid, packageName);
     }
 
     @Override
-    public int[] getRequestingUidsForType(String accountType) {
+    public Map<Integer, Integer> getUidsAndVisibilityForAccount(Account account) {
+        if (account == null) throw new IllegalArgumentException("account is null");
         int callingUid = Binder.getCallingUid();
-        if (!isAccountManagedByCaller(accountType, callingUid, UserHandle.getUserId(callingUid))) {
-            String msg = String.format(
-                    "uid %s cannot get secrets for accounts of type: %s",
-                    callingUid,
-                    accountType);
+        int userId = UserHandle.getUserId(callingUid);
+        UserAccounts accounts = getUserAccounts(userId);
+        if (!isAccountManagedByCaller(account.type, callingUid, userId)
+                && !isSystemUid(callingUid)) {
+            String msg =
+                    String.format("uid %s cannot get secrets for account %s", callingUid, account);
             throw new SecurityException(msg);
         }
-        // TODO Implement.
-        return new int[]{};
+        return getUidsAndVisibilityForAccount(account, accounts);
+    }
+
+    /**
+     * Returns all UIDs and visibility values, which were set for given account
+     *
+     * @param account account
+     * @param accounts UserAccount that currently hosts the account and application
+     *
+     * @return Map from uid to visibility.
+     */
+    private Map<Integer, Integer> getUidsAndVisibilityForAccount(Account account,
+            UserAccounts accounts) {
+        final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+        try {
+            return accounts.accountsDb.findAllVisibilityValuesForAccount(account);
+        } finally {
+            StrictMode.setThreadPolicy(oldPolicy);
+        }
+
     }
 
     @Override
     public int getAccountVisibility(Account a, int uid) {
-        // TODO Implement.
-        return 0;
+        if (a == null) throw new IllegalArgumentException("account is null");
+        int callingUid = Binder.getCallingUid();
+        if (!isAccountManagedByCaller(a.type, callingUid, UserHandle.getUserId(callingUid))
+            && !isSystemUid(callingUid)) {
+            String msg = String.format(
+                    "uid %s cannot get secrets for accounts of type: %s",
+                    callingUid,
+                    a.type);
+            throw new SecurityException(msg);
+        }
+        return getAccountVisibility(a, uid, getUserAccounts(UserHandle.getUserId(callingUid)));
+    }
+
+    /**
+     * Method gets visibility for given account and UID from the database
+     *
+     * @param account The account to check visibility of
+     * @param uid UID to check visibility of
+     * @param accounts UserAccount that currently hosts the account and application
+     *
+     * @return Visibility value, AccountManager.VISIBILITY_UNDEFINED if no value was stored.
+     *
+     */
+    private int getAccountVisibility(Account account, int uid, UserAccounts accounts) {
+        final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+        try {
+            Integer visibility = accounts.accountsDb.findAccountVisibility(account, uid);
+            return visibility != null ? visibility : AccountManager.VISIBILITY_UNDEFINED;
+        } finally {
+            StrictMode.setThreadPolicy(oldPolicy);
+        }
+    }
+
+    /**
+     * Method which handles default values for Account visibility.
+     *
+     * @param account The account to check visibility.
+     * @param uid UID to check visibility.
+     * @param packageName Package name to check visibility - the method assumes that it has the same
+     *        uid as specified in the parameter.
+     * @param accounts UserAccount that currently hosts the account and application
+     *
+     * @return Visibility value, the method never returns AccountManager.VISIBILITY_UNDEFINED
+     *
+     */
+    private Integer resolveAccountVisibility(Account account, int uid, String packageName,
+            UserAccounts accounts) {
+        if (packageName == null) {
+            packageName = getPackageNameForUid(uid);
+        }
+        // System visibility can not be restricted.
+        if (UserHandle.isSameApp(uid, Process.SYSTEM_UID)) {
+            return AccountManager.VISIBILITY_VISIBLE;
+        }
+
+        int signatureCheckResult =
+                checkPackageSignature(account.type, uid, accounts.userId);
+
+        // Authenticator can not restrict visibility to itself.
+        if (signatureCheckResult == SIGNATURE_CHECK_UID_MATCH) {
+            return AccountManager.VISIBILITY_VISIBLE; // Authenticator can always see the account
+        }
+
+        // Return stored value if it was set.
+        int visibility = getAccountVisibility(account, uid, accounts);
+
+        if (AccountManager.VISIBILITY_UNDEFINED != visibility) {
+            return visibility;
+        }
+
+        if (isPermittedForPackage(packageName, accounts.userId,
+                Manifest.permission.GET_ACCOUNTS_PRIVILEGED)) {
+            return AccountManager.VISIBILITY_VISIBLE;
+
+        }
+        // Profile owner gets visibility by default.
+        if(isProfileOwner(uid)) {
+            return AccountManager.VISIBILITY_VISIBLE;
+        }
+        // Apps with READ_CONTACTS permission get visibility by default even post O.
+        boolean canReadContacts = checkReadContactsPermission(packageName, accounts.userId);
+
+        boolean preO = isPreOApplication(packageName);
+        if ((signatureCheckResult != SIGNATURE_CHECK_MISMATCH)
+                || (preO && checkGetAccountsPermission(packageName, accounts.userId))
+                || canReadContacts) {
+            // Use legacy for preO apps with GET_ACCOUNTS permission or pre/postO with signature
+            // match.
+            visibility = getAccountVisibility(account,
+                    AccountManager.UID_KEY_DEFAULT_LEGACY_VISIBILITY, accounts);
+            if (AccountManager.VISIBILITY_UNDEFINED == visibility) {
+                visibility = AccountManager.VISIBILITY_USER_MANAGED_VISIBLE;
+            }
+        } else {
+            visibility = getAccountVisibility(account, AccountManager.UID_KEY_DEFAULT_VISIBILITY,
+                    accounts);
+            if (AccountManager.VISIBILITY_UNDEFINED == visibility) {
+                visibility = AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE;
+            }
+        }
+        return visibility;
+    }
+
+    /**
+     * Checks targetSdk for a package;
+     *
+     * @param packageName Package Name
+     *
+     * @return True if package's target SDK is below {@link android.os.Build.VERSION_CODES#O}, or
+     *         undefined
+     */
+    private boolean isPreOApplication(String packageName) {
+        try {
+            long identityToken = clearCallingIdentity();
+            ApplicationInfo applicationInfo;
+            try {
+                applicationInfo = mPackageManager.getApplicationInfo(packageName, 0);
+            } finally {
+                restoreCallingIdentity(identityToken);
+            }
+
+            if (applicationInfo != null) {
+                int version = applicationInfo.targetSdkVersion;
+                return version < android.os.Build.VERSION_CODES.O;
+            }
+            return true;
+        } catch (NameNotFoundException e) {
+            Log.d(TAG, "Package not found " + e.getMessage());
+            return true;
+        }
     }
 
     @Override
-    public boolean setAccountVisibility(Account a, int uid, int visibility) {
-        // TODO Implement.
-        return false;
-    }
-
-    /**
-     * Registers the requested login account types requested by all the applications already
-     * installed on the device.
-     */
-    private void addRequestsForPreInstalledApplications() {
-        List<PackageInfo> allInstalledPackages = mPackageManager.getInstalledPackages(0);
-        for(PackageInfo pi : allInstalledPackages) {
-            int currentUid = pi.applicationInfo.uid;
-            if(currentUid != -1) {
-                registerAccountTypesSupported(currentUid,
-                        getUserAccounts(UserHandle.getUserId(currentUid)));
-            }
+    public boolean setAccountVisibility(Account a, int uid, int newVisibility) {
+        if (a == null) throw new IllegalArgumentException("account is null");
+        int callingUid = Binder.getCallingUid();
+        if (!isAccountManagedByCaller(a.type, callingUid, UserHandle.getUserId(callingUid))
+            && !isSystemUid(callingUid)) {
+            String msg = String.format(
+                    "uid %s cannot get secrets for accounts of type: %s",
+                    callingUid,
+                    a.type);
+            throw new SecurityException(msg);
         }
+        return setAccountVisibility(a, uid, newVisibility, true /* notify */,
+                getUserAccounts(UserHandle.getUserId(callingUid)));
     }
 
     /**
-     * Registers an application, represented by a UID, to support account types detailed in the
-     * applications manifest as well as allowing it to opt for notifications.
+     * Gives a certain UID, represented a application, access to an account. This method
+     * is called indirectly by the Authenticator.
      *
-     * @param uid UID of application
-     * @param ua UserAccount that currently hosts the account and application
+     * @param account Account to update visibility
+     * @param uid to add visibility of the Account
+     * @param newVisibility new visibility
+     * @param notify if the flag is set applications will get notification about visibility change
+     * @param accounts UserAccount that currently hosts the account and application
+     *
+     * @return True if account visibility was changed.
      */
-    private void registerAccountTypesSupported(int uid, UserAccounts ua) {
-        return;
-        // TODO clean up the code, manifest entry is deprecated
-        /*
-        String interestedPackages = null;
-        try {
-            String[] allPackages = mPackageManager.getPackagesForUid(uid);
-            if (allPackages != null) {
-                for (String aPackage : allPackages) {
-                    ApplicationInfo ai = mPackageManager.getApplicationInfo(aPackage,
-                            PackageManager.GET_META_DATA);
-                    Bundle b = ai.metaData;
-                    if (b == null) {
-                        return;
+    private boolean setAccountVisibility(Account account, int uid, int newVisibility,
+            boolean notify, UserAccounts accounts) {
+        synchronized (accounts.cacheLock) {
+            LinkedHashSet<String> interestedPackages;
+            if (notify) {
+                if (uid < 0) {
+                    interestedPackages = getRequestingPackageNames(account.type, accounts);
+                } else {
+                    interestedPackages = new LinkedHashSet<>();
+                    String[] subPackages = mPackageManager.getPackagesForUid(uid);
+                    if (subPackages != null) {
+                        Collections.addAll(interestedPackages, subPackages);
                     }
-                    interestedPackages = b.getString(AccountManager.SUPPORTED_ACCOUNT_TYPES);
+                }
+            } else {
+                // Notifications will not be send.
+                interestedPackages = new LinkedHashSet<>();
+            }
+            Integer[] interestedPackagesVisibility = new Integer[interestedPackages.size()];
+
+            final long accountId = accounts.accountsDb.findDeAccountId(account);
+            if (accountId < 0) {
+                return false;
+            }
+            int index = 0;
+            for (String packageName : interestedPackages) {
+                interestedPackagesVisibility[index++] =
+                        resolveAccountVisibility(account, uid, packageName, accounts);
+            }
+
+            final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
+            try {
+                if (!accounts.accountsDb.setAccountVisibility(accountId, uid, newVisibility)) {
+                    return false;
+                }
+            } finally {
+                StrictMode.setThreadPolicy(oldPolicy);
+            }
+
+            index = 0;
+            for (String packageName : interestedPackages) {
+                int visibility = resolveAccountVisibility(account, uid, packageName, accounts);
+                if (visibility != interestedPackagesVisibility[index++]) {
+                        sendNotification(packageName, account, accounts.userId);
                 }
             }
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.d("NameNotFoundException", e.getMessage());
+            if (notify) {
+                sendAccountsChangedBroadcast(accounts.userId);
+            }
+            return true;
         }
-        if (interestedPackages != null) {
-            // TODO request visibility
-            // requestAccountVisibility(interestedPackages.split(";"), uid, ua);
-        }
-        */
     }
 
     /**
      * Sends a direct intent to a package, notifying it of a visible account change.
      *
-     * @param desiredPackage to send Account to
-     * @param visibleAccount to send to package
+     * @param packageName to send Account to
+     * @param account to send to package
+     * @param userId User
      */
-    private void sendNotification(String desiredPackage, Account visibleAccount) {
-        // TODO replace with callback
-        /*
-        Intent intent = new Intent();
-        intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
-        intent.setAction(AccountManager.ACTION_VISIBLE_ACCOUNTS_CHANGED);
-        intent.setPackage(desiredPackage);
-        // TODO update documentation, add account extra if new account became visible
-        // intent.putExtra("android.accounts.KEY_ACCOUNT", (Account) visibleAccount);
-        mContext.sendBroadcast(intent);
-        */
+    private void sendNotification(String packageName, Account account, int userId) {
+        // TODO send notification so apps subscribed in runtime.
+    }
+
+    private void sendNotification(Account account, UserAccounts accounts) {
+        LinkedHashSet<String> interestedPackages = getRequestingPackageNames(account.type,
+                accounts);
+        for (String packageName : interestedPackages) {
+            try {
+                final int uid = mPackageManager.getPackageUidAsUser(packageName, accounts.userId);
+                int visibility = resolveAccountVisibility(account, uid, packageName, accounts);
+                if (visibility != AccountManager.VISIBILITY_NOT_VISIBLE) {
+                    sendNotification(packageName, account, accounts.userId);
+                }
+            } catch (NameNotFoundException e) {
+                // ignore
+            }
+        }
+    }
+
+    LinkedHashSet<String> getRequestingPackageNames(String accountType, UserAccounts accouns) {
+        // TODO return packages registered to get notifications.
+        return new LinkedHashSet<String>();
+    }
+
+    private void sendAccountsChangedBroadcast(int userId) {
+        Log.i(TAG, "the accounts changed, sending broadcast of "
+                + ACCOUNTS_CHANGED_INTENT.getAction());
+        mContext.sendBroadcastAsUser(ACCOUNTS_CHANGED_INTENT, new UserHandle(userId));
     }
 
     @Override
@@ -688,6 +937,12 @@
                         accounts.userDataCache.remove(account);
                         accounts.authTokenCache.remove(account);
                         accounts.accountTokenCaches.remove(account);
+                        LinkedHashSet<String> interestedPackages =
+                                getRequestingPackageNames(account.type, accounts);
+                        for (String packageName : interestedPackages) {
+                            sendNotification(packageName, null, accounts.userId);
+                        }
+
                     } else {
                         ArrayList<String> accountNames = accountNamesByType.get(account.type);
                         if (accountNames == null) {
@@ -792,7 +1047,7 @@
                     AccountsDb.TABLE_ACCOUNTS);
 
             for (Account account : accountsToRemove) {
-                removeAccountInternal(accounts, account, Process.myUid());
+                removeAccountInternal(accounts, account, Process.SYSTEM_UID);
             }
         }
     }
@@ -1049,7 +1304,7 @@
 
     private boolean isCrossUser(int callingUid, int userId) {
         return (userId != UserHandle.getCallingUserId()
-                && callingUid != Process.myUid()
+                && callingUid != Process.SYSTEM_UID
                 && mContext.checkCallingOrSelfPermission(
                         android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
                                 != PackageManager.PERMISSION_GRANTED);
@@ -1057,42 +1312,7 @@
 
     @Override
     public boolean addAccountExplicitly(Account account, String password, Bundle extras) {
-        Bundle.setDefusable(extras, true);
-        // clears the visible list functionality for this account because this method allows
-        // default account access to all applications for account.
-
-        final int callingUid = Binder.getCallingUid();
-        if (Log.isLoggable(TAG, Log.VERBOSE)) {
-            Log.v(TAG, "addAccountExplicitly: " + account
-                    + ", caller's uid " + callingUid
-                    + ", pid " + Binder.getCallingPid());
-        }
-        if (account == null) throw new IllegalArgumentException("account is null");
-        int userId = UserHandle.getCallingUserId();
-        if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
-            String msg = String.format(
-                    "uid %s cannot explicitly add accounts of type: %s",
-                    callingUid,
-                    account.type);
-            throw new SecurityException(msg);
-        }
-
-        /*
-         * Child users are not allowed to add accounts. Only the accounts that are
-         * shared by the parent profile can be added to child profile.
-         *
-         * TODO: Only allow accounts that were shared to be added by
-         *     a limited user.
-         */
-
-        // fails if the account already exists
-        long identityToken = clearCallingIdentity();
-        try {
-            UserAccounts accounts = getUserAccounts(userId);
-            return addAccountInternal(accounts, account, password, extras, callingUid);
-        } finally {
-            restoreCallingIdentity(identityToken);
-        }
+        return addAccountExplicitlyWithVisibility(account, password, extras, null);
     }
 
     @Override
@@ -1233,6 +1453,8 @@
                     // TODO: Anything to do if if succedded?
                     // TODO: If it failed: Show error notification? Should we remove the shadow
                     // account to avoid retries?
+                    // TODO: what we do with the visibility?
+
                     super.onResult(result);
                 }
 
@@ -1250,7 +1472,7 @@
     }
 
     private boolean addAccountInternal(UserAccounts accounts, Account account, String password,
-            Bundle extras, int callingUid) {
+            Bundle extras, int callingUid, Map<Integer, Integer> uidToVisibility) {
         Bundle.setDefusable(extras, true);
         if (account == null) {
             return false;
@@ -1290,10 +1512,17 @@
                         }
                     }
                 }
+
+                if (uidToVisibility != null) {
+                    for (Entry<Integer, Integer> entry : uidToVisibility.entrySet()) {
+                        setAccountVisibility(account, entry.getKey() /* uid */,
+                                entry.getValue() /* visibility */, false /* notify */, accounts);
+                    }
+                }
                 accounts.accountsDb.setTransactionSuccessful();
 
-                logRecord(AccountsDb.DEBUG_ACTION_ACCOUNT_ADD, AccountsDb.TABLE_ACCOUNTS,
-                        accountId, accounts, callingUid);
+                logRecord(AccountsDb.DEBUG_ACTION_ACCOUNT_ADD, AccountsDb.TABLE_ACCOUNTS, accountId,
+                        accounts, callingUid);
 
                 insertAccountIntoCacheLocked(accounts, account);
             } finally {
@@ -1304,8 +1533,10 @@
             addAccountToLinkedRestrictedUsers(account, accounts.userId);
         }
 
+        sendNotification(account, accounts);
         // Only send LOGIN_ACCOUNTS_CHANGED when the database changed.
         sendAccountsChangedBroadcast(accounts.userId);
+
         return true;
     }
 
@@ -1482,6 +1713,10 @@
         synchronized (accounts.cacheLock) {
             accounts.accountsDb.beginTransaction();
             Account renamedAccount = new Account(newName, accountToRename.type);
+            if ((accounts.accountsDb.findCeAccountId(renamedAccount) >= 0)) {
+                Log.e(TAG, "renameAccount failed - account with new name already exists");
+                return null;
+            }
             try {
                 final long accountId = accounts.accountsDb.findDeAccountId(accountToRename);
                 if (accountId >= 0) {
@@ -1493,6 +1728,9 @@
                         Log.e(TAG, "renameAccount failed");
                         return null;
                     }
+                } else {
+                    Log.e(TAG, "renameAccount failed - old account does not exist");
+                    return null;
                 }
             } finally {
                 accounts.accountsDb.endTransaction();
@@ -1535,6 +1773,9 @@
                     }
                 }
             }
+
+            // Notify authenticator.
+            sendNotification(resultAccount, accounts);
             sendAccountsChangedBroadcast(accounts.userId);
         }
         return resultAccount;
@@ -1733,6 +1974,24 @@
                     + " is still locked. CE data will be removed later");
         }
         synchronized (accounts.cacheLock) {
+            LinkedHashSet<String> interestedPackages =
+                    accounts.mApplicationAccountRequestMappings.get(account.type);
+            if (interestedPackages == null) {
+                interestedPackages = new LinkedHashSet<>();
+            }
+            int[] visibilityForInterestedPackages = new int[interestedPackages.size()];
+            int index = 0;
+            for (String packageName : interestedPackages) {
+                int visibility = AccountManager.VISIBILITY_NOT_VISIBLE;
+                try {
+                    final int uid = mPackageManager.getPackageUidAsUser(packageName,
+                            UserHandle.getUserId(callingUid));
+                    visibility = resolveAccountVisibility(account, uid, packageName, accounts);
+                } catch (NameNotFoundException e) {
+                    // ignore
+                }
+                visibilityForInterestedPackages[index++] = visibility;
+            }
             accounts.accountsDb.beginTransaction();
             // Set to a dummy value, this will only be used if the database
             // transaction succeeds.
@@ -1756,6 +2015,17 @@
             }
             if (isChanged) {
                 removeAccountFromCacheLocked(accounts, account);
+                index = 0;
+                for (String packageName : interestedPackages) {
+                    if ((visibilityForInterestedPackages[index]
+                            != AccountManager.VISIBILITY_NOT_VISIBLE)
+                            && (visibilityForInterestedPackages[index]
+                                    != AccountManager.VISIBILITY_UNDEFINED)) {
+                        sendNotification(packageName, account, accounts.userId);
+                    }
+                    ++index;
+                }
+
                 // Only broadcast LOGIN_ACCOUNTS_CHANGED if a change occured.
                 sendAccountsChangedBroadcast(accounts.userId);
                 String action = userUnlocked ? AccountsDb.DEBUG_ACTION_ACCOUNT_REMOVE
@@ -2022,18 +2292,13 @@
                 accounts.accountsDb.endTransaction();
                 if (isChanged) {
                     // Send LOGIN_ACCOUNTS_CHANGED only if the something changed.
+                    sendNotification(account, accounts);
                     sendAccountsChangedBroadcast(accounts.userId);
                 }
             }
         }
     }
 
-    private void sendAccountsChangedBroadcast(int userId) {
-        Log.i(TAG, "the accounts changed, sending broadcast of "
-                + ACCOUNTS_CHANGED_INTENT.getAction());
-        mContext.sendBroadcastAsUser(ACCOUNTS_CHANGED_INTENT, new UserHandle(userId));
-    }
-
     @Override
     public void clearPassword(Account account) {
         final int callingUid = Binder.getCallingUid();
@@ -2412,8 +2677,10 @@
                             checkKeyIntent(
                                     Binder.getCallingUid(),
                                     intent);
-                            doNotification(mAccounts,
-                                    account, result.getString(AccountManager.KEY_AUTH_FAILED_MESSAGE),
+                            doNotification(
+                                    mAccounts,
+                                    account,
+                                    result.getString(AccountManager.KEY_AUTH_FAILED_MESSAGE),
                                     intent, "android", accounts.userId);
                         }
                     }
@@ -3298,7 +3565,8 @@
         if (response == null) throw new IllegalArgumentException("response is null");
         if (accountType == null) throw new IllegalArgumentException("accountType is null");
         int userId = UserHandle.getCallingUserId();
-        if (!isAccountManagedByCaller(accountType, callingUid, userId) && !isSystemUid(callingUid)) {
+        if (!isAccountManagedByCaller(accountType, callingUid, userId)
+                && !isSystemUid(callingUid)) {
             String msg = String.format(
                     "uid %s cannot edit authenticator properites for account type: %s",
                     callingUid,
@@ -3341,23 +3609,50 @@
         Preconditions.checkArgumentInRange(userId, 0, Integer.MAX_VALUE, "user must be concrete");
 
         try {
-            final int uid = mPackageManager.getPackageUidAsUser(packageName, userId);
+            int uid = mPackageManager.getPackageUidAsUser(packageName, userId);
             return hasAccountAccess(account, packageName, uid);
         } catch (NameNotFoundException e) {
+            Log.d(TAG, "Package not found " + e.getMessage());
             return false;
         }
     }
 
+    // Returns package with oldest target SDK for given UID.
+    private String getPackageNameForUid(int uid) {
+        String[] packageNames = mPackageManager.getPackagesForUid(uid);
+        if (ArrayUtils.isEmpty(packageNames)) {
+            return null;
+        }
+        // For app op checks related to permissions all packages in the UID
+        // have the same app op state, so doesn't matter which one we pick.
+        // Update: due to visibility changes we want to use package with oldest target SDK,
+
+        String packageName = packageNames[0];
+        int oldestVersion = Integer.MAX_VALUE;
+        for (String name : packageNames) {
+            try {
+                ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(name, 0);
+                if (applicationInfo != null) {
+                    int version = applicationInfo.targetSdkVersion;
+                    if (version < oldestVersion) {
+                        oldestVersion = version;
+                        packageName = name;
+                    }
+                }
+            } catch (NameNotFoundException e) {
+                // skip
+            }
+        }
+        return packageName;
+    }
+
     private boolean hasAccountAccess(@NonNull Account account, @Nullable String packageName,
             int uid) {
         if (packageName == null) {
-            String[] packageNames = mPackageManager.getPackagesForUid(uid);
-            if (ArrayUtils.isEmpty(packageNames)) {
+            packageName = getPackageNameForUid(uid);
+            if (packageName == null) {
                 return false;
             }
-            // For app op checks related to permissions all packages in the UID
-            // have the same app op state, so doesn't matter which one we pick.
-            packageName = packageNames[0];
         }
 
         // Use null token which means any token. Having a token means the package
@@ -3366,27 +3661,12 @@
             return true;
         }
         // In addition to the permissions required to get an auth token we also allow
-        // the account to be accessed by holders of the get accounts permissions.
-        return checkUidPermission(Manifest.permission.GET_ACCOUNTS_PRIVILEGED, uid, packageName)
-                || checkUidPermission(Manifest.permission.GET_ACCOUNTS, uid, packageName);
-    }
+        // the account to be accessed by apps for which user or authenticator granted visibility.
 
-    private boolean checkUidPermission(String permission, int uid, String opPackageName) {
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            IPackageManager pm = ActivityThread.getPackageManager();
-            if (pm.checkUidPermission(permission, uid) != PackageManager.PERMISSION_GRANTED) {
-                return false;
-            }
-            final int opCode = AppOpsManager.permissionToOpCode(permission);
-            return (opCode == AppOpsManager.OP_NONE || mAppOpsManager.noteOpNoThrow(
-                    opCode, uid, opPackageName) == AppOpsManager.MODE_ALLOWED);
-        } catch (RemoteException e) {
-            /* ignore - local call */
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-        return false;
+        int visibility = resolveAccountVisibility(account, uid, packageName,
+                getUserAccounts(UserHandle.getUserId(uid)));
+        return (visibility == AccountManager.VISIBILITY_VISIBLE
+                || visibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
     }
 
     @Override
@@ -3482,21 +3762,28 @@
         private volatile ArrayList<Account> mAccountsWithFeatures = null;
         private volatile int mCurrentAccount = 0;
         private final int mCallingUid;
+        private final String mPackageName;
 
-        public GetAccountsByTypeAndFeatureSession(UserAccounts accounts,
-                IAccountManagerResponse response, String type, String[] features, int callingUid) {
+        public GetAccountsByTypeAndFeatureSession(
+                UserAccounts accounts,
+                IAccountManagerResponse response,
+                String type,
+                String[] features,
+                int callingUid,
+                String packageName) {
             super(accounts, response, type, false /* expectActivityLaunch */,
                     true /* stripAuthTokenFromResult */, null /* accountName */,
                     false /* authDetailsRequired */);
             mCallingUid = callingUid;
             mFeatures = features;
+            mPackageName = packageName;
         }
 
         @Override
         public void run() throws RemoteException {
             synchronized (mAccounts.cacheLock) {
                 mAccountsOfType = getAccountsFromCacheLocked(mAccounts, mAccountType, mCallingUid,
-                        null);
+                        mPackageName, false /* include managed not visible*/);
             }
             // check whether each account matches the requested features
             mAccountsWithFeatures = new ArrayList<>(mAccountsOfType.length);
@@ -3569,7 +3856,6 @@
             }
         }
 
-
         @Override
         protected String toDebugString(long now) {
             return super.toDebugString(now) + ", getAccountsByTypeAndFeatures"
@@ -3595,8 +3881,9 @@
             return getAccountsInternal(
                     accounts,
                     callingUid,
-                    null,  // packageName
-                    visibleAccountTypes);
+                    opPackageName,
+                    visibleAccountTypes,
+                    false /* includeUserManagedNotVisible */);
         } finally {
             restoreCallingIdentity(identityToken);
         }
@@ -3638,7 +3925,9 @@
             if (userAccounts == null) continue;
             synchronized (userAccounts.cacheLock) {
                 Account[] accounts = getAccountsFromCacheLocked(userAccounts, null,
-                        Binder.getCallingUid(), null);
+                        Binder.getCallingUid(),
+                        null,
+                        false /* incl managed not visible*/);
                 for (int a = 0; a < accounts.length; a++) {
                     runningAccounts.add(new AccountAndUser(accounts[a], userId));
                 }
@@ -3652,7 +3941,9 @@
     @Override
     @NonNull
     public Account[] getAccountsAsUser(String type, int userId, String opPackageName) {
-        return getAccountsAsUser(type, userId, null, -1, opPackageName);
+        // Need calling package
+        return getAccountsAsUser(type, userId, null /* callingPackage */, -1, opPackageName,
+               false /* includeUserManagedNotVisible */);
     }
 
     @NonNull
@@ -3661,11 +3952,12 @@
             int userId,
             String callingPackage,
             int packageUid,
-            String opPackageName) {
+            String opPackageName,
+            boolean includeUserManagedNotVisible) {
         int callingUid = Binder.getCallingUid();
         // Only allow the system process to read accounts of other users
         if (userId != UserHandle.getCallingUserId()
-                && callingUid != Process.myUid()
+                && callingUid != Process.SYSTEM_UID
                 && mContext.checkCallingOrSelfPermission(
                     android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
                     != PackageManager.PERMISSION_GRANTED) {
@@ -3678,9 +3970,15 @@
                     + ", caller's uid " + Binder.getCallingUid()
                     + ", pid " + Binder.getCallingPid());
         }
-        // If the original calling app was using the framework account chooser activity, we'll
-        // be passed in the original caller's uid here, which is what should be used for filtering.
-        if (packageUid != -1 && UserHandle.isSameApp(callingUid, Process.myUid())) {
+
+        // If the original calling app was using account choosing activity
+        // provided by the framework or authenticator we'll passing in
+        // the original caller's uid here, which is what should be used for filtering.
+        List<String> managedTypes =
+                getTypesManagedByCaller(callingUid, UserHandle.getUserId(callingUid));
+        if (packageUid != -1 &&
+                ((UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
+                || (type != null && managedTypes.contains(type))))) {
             callingUid = packageUid;
             opPackageName = callingPackage;
         }
@@ -3688,7 +3986,7 @@
                 opPackageName);
         if (visibleAccountTypes.isEmpty()
                 || (type != null && !visibleAccountTypes.contains(type))) {
-            return new Account[0];
+            return new Account[]{};
         } else if (visibleAccountTypes.contains(type)) {
             // Prune the list down to just the requested type.
             visibleAccountTypes = new ArrayList<>();
@@ -3703,7 +4001,8 @@
                     accounts,
                     callingUid,
                     callingPackage,
-                    visibleAccountTypes);
+                    visibleAccountTypes,
+                    includeUserManagedNotVisible);
         } finally {
             restoreCallingIdentity(identityToken);
         }
@@ -3714,12 +4013,14 @@
             UserAccounts userAccounts,
             int callingUid,
             String callingPackage,
-            List<String> visibleAccountTypes) {
+            List<String> visibleAccountTypes,
+            boolean includeUserManagedNotVisible) {
         synchronized (userAccounts.cacheLock) {
             ArrayList<Account> visibleAccounts = new ArrayList<>();
             for (String visibleType : visibleAccountTypes) {
                 Account[] accountsForType = getAccountsFromCacheLocked(
-                        userAccounts, visibleType, callingUid, callingPackage);
+                        userAccounts, visibleType, callingUid, callingPackage,
+                        includeUserManagedNotVisible);
                 if (accountsForType != null) {
                     visibleAccounts.addAll(Arrays.asList(accountsForType));
                 }
@@ -3810,29 +4111,34 @@
     @NonNull
     public Account[] getAccountsForPackage(String packageName, int uid, String opPackageName) {
         int callingUid = Binder.getCallingUid();
-        if (!UserHandle.isSameApp(callingUid, Process.myUid())) {
+        if (!UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)) {
             throw new SecurityException("getAccountsForPackage() called from unauthorized uid "
                     + callingUid + " with uid=" + uid);
         }
         return getAccountsAsUser(null, UserHandle.getCallingUserId(), packageName, uid,
-                opPackageName);
+                opPackageName, true /* includeUserManagedNotVisible */);
     }
 
     @Override
     @NonNull
     public Account[] getAccountsByTypeForPackage(String type, String packageName,
             String opPackageName) {
+        int callingUid =  Binder.getCallingUid();
+        int userId = UserHandle.getCallingUserId();
         int packageUid = -1;
         try {
-            packageUid = AppGlobals.getPackageManager().getPackageUid(
-                    packageName, PackageManager.MATCH_UNINSTALLED_PACKAGES,
-                    UserHandle.getCallingUserId());
-        } catch (RemoteException re) {
+            packageUid = mPackageManager.getPackageUidAsUser(packageName, userId);
+        } catch (NameNotFoundException re) {
             Slog.e(TAG, "Couldn't determine the packageUid for " + packageName + re);
             return new Account[0];
         }
-        return getAccountsAsUser(type, UserHandle.getCallingUserId(), packageName,
-                packageUid, opPackageName);
+        if (!UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
+                && !isAccountManagedByCaller(type, callingUid, userId)) {
+            return new Account[0];
+        }
+
+        return getAccountsAsUser(type, userId,
+                packageName, packageUid, opPackageName, true /* includeUserManagedNotVisible */);
     }
 
     @Override
@@ -3872,7 +4178,8 @@
             if (features == null || features.length == 0) {
                 Account[] accounts;
                 synchronized (userAccounts.cacheLock) {
-                    accounts = getAccountsFromCacheLocked(userAccounts, type, callingUid, null);
+                    accounts = getAccountsFromCacheLocked(
+                            userAccounts, type, callingUid, opPackageName, false);
                 }
                 Bundle result = new Bundle();
                 result.putParcelableArray(AccountManager.KEY_ACCOUNTS, accounts);
@@ -3884,7 +4191,8 @@
                     response,
                     type,
                     features,
-                    callingUid).bind();
+                    callingUid,
+                    opPackageName).bind();
         } finally {
             restoreCallingIdentity(identityToken);
         }
@@ -3903,6 +4211,7 @@
                 if (Objects.equals(account.getAccessId(), token)) {
                     // An app just accessed the account. At this point it knows about
                     // it and there is not need to hide this account from the app.
+                    // Do we need to update account visibility here?
                     if (!hasAccountAccess(account, null, uid)) {
                         updateAppPermission(account, AccountManager.ACCOUNT_ACCESS_TOKEN_TYPE,
                                 uid, true);
@@ -4429,7 +4738,7 @@
                 userAccounts.accountsDb.dumpDeAccountsTable(fout);
             } else {
                 Account[] accounts = getAccountsFromCacheLocked(userAccounts, null /* type */,
-                        Process.myUid(), null);
+                        Process.SYSTEM_UID, null, false);
                 fout.println("Accounts: " + accounts.length);
                 for (Account account : accounts) {
                     fout.println("  " + account);
@@ -4522,6 +4831,24 @@
         }
     }
 
+    private boolean isPermittedForPackage(String packageName, int userId, String... permissions) {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            IPackageManager pm = ActivityThread.getPackageManager();
+            for (String perm : permissions) {
+                if (pm.checkPermission(perm, packageName, userId)
+                        == PackageManager.PERMISSION_GRANTED) {
+                    return true;
+                }
+            }
+        } catch (RemoteException e) {
+            /* ignore - local call */
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+        return false;
+    }
+
     private boolean isPermitted(String opPackageName, int callingUid, String... permissions) {
         for (String perm : permissions) {
             if (mContext.checkCallingOrSelfPermission(perm) == PackageManager.PERMISSION_GRANTED) {
@@ -4556,6 +4883,7 @@
             userPackageManager = mContext.createPackageContextAsUser(
                     "android", 0, new UserHandle(callingUserId)).getPackageManager();
         } catch (NameNotFoundException e) {
+            Log.d(TAG, "Package not found " + e.getMessage());
             return false;
         }
 
@@ -4569,6 +4897,7 @@
                     return true;
                 }
             } catch (PackageManager.NameNotFoundException e) {
+                Log.d(TAG, "Package not found " + e.getMessage());
                 return false;
             }
         }
@@ -4623,6 +4952,53 @@
         }
     }
 
+    // Method checks visibility for applications targeing API level below {@link
+    // android.os.Build.VERSION_CODES#O},
+    // returns true if the the app has GET_ACCOUNTS or GET_ACCOUNTS_PRIVELEGED permission.
+    private boolean checkGetAccountsPermission(String packageName, int userId) {
+        return isPermittedForPackage(packageName, userId, Manifest.permission.GET_ACCOUNTS,
+                Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
+    }
+
+    private boolean checkReadContactsPermission(String packageName, int userId) {
+        return isPermittedForPackage(packageName, userId, Manifest.permission.READ_CONTACTS);
+    }
+
+    /**
+     * Method checks package uid and signature with Authenticator which manages accountType.
+     *
+     * @return SIGNATURE_CHECK_UID_MATCH for uid match, SIGNATURE_CHECK_MATCH for signature match,
+     *         SIGNATURE_CHECK_MISMATCH otherwise.
+     */
+    private int checkPackageSignature(String accountType, int callingUid, int userId) {
+        if (accountType == null) {
+            return SIGNATURE_CHECK_MISMATCH;
+        }
+
+        long identityToken = Binder.clearCallingIdentity();
+        Collection<RegisteredServicesCache.ServiceInfo<AuthenticatorDescription>> serviceInfos;
+        try {
+            serviceInfos = mAuthenticatorCache.getAllServices(userId);
+        } finally {
+            Binder.restoreCallingIdentity(identityToken);
+        }
+        // Check for signature match with Authenticator.
+        for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo
+                : serviceInfos) {
+            if (accountType.equals(serviceInfo.type.type)) {
+                if (serviceInfo.uid == callingUid) {
+                    return SIGNATURE_CHECK_UID_MATCH;
+                }
+                final int sigChk = mPackageManager.checkSignatures(serviceInfo.uid, callingUid);
+                if (sigChk == PackageManager.SIGNATURE_MATCH) {
+                    return SIGNATURE_CHECK_MATCH;
+                }
+            }
+        }
+        return SIGNATURE_CHECK_MISMATCH;
+    }
+
+    // returns true for applications with the same signature as authenticator.
     private boolean isAccountManagedByCaller(String accountType, int callingUid, int userId) {
         if (accountType == null) {
             return false;
@@ -4633,10 +5009,7 @@
 
     private List<String> getTypesVisibleToCaller(int callingUid, int userId,
             String opPackageName) {
-        boolean isPermitted =
-                isPermitted(opPackageName, callingUid, Manifest.permission.GET_ACCOUNTS,
-                        Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
-        return getTypesForCaller(callingUid, userId, isPermitted);
+        return getTypesForCaller(callingUid, userId, true /* isOtherwisePermitted*/);
     }
 
     private List<String> getTypesManagedByCaller(int callingUid, int userId) {
@@ -4655,8 +5028,8 @@
         }
         for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo :
                 serviceInfos) {
-            final int sigChk = mPackageManager.checkSignatures(serviceInfo.uid, callingUid);
-            if (isOtherwisePermitted || sigChk == PackageManager.SIGNATURE_MATCH) {
+            if (isOtherwisePermitted || (mPackageManager.checkSignatures(serviceInfo.uid,
+                    callingUid) == PackageManager.SIGNATURE_MATCH)) {
                 managedAccountTypes.add(serviceInfo.type.type);
             }
         }
@@ -4738,7 +5111,7 @@
                                     != 0) {
                         return true;
                     }
-                } catch (PackageManager.NameNotFoundException e) {
+                } catch (NameNotFoundException e) {
                     Log.w(TAG, String.format("Could not find package [%s]", name), e);
                 }
             }
@@ -4929,15 +5302,41 @@
         return newAccountsForType[oldLength];
     }
 
-    private Account[] filterSharedAccounts(UserAccounts userAccounts, Account[] unfiltered,
-            int callingUid, String callingPackage) {
+    private Account[] filterAccounts(UserAccounts accounts, Account[] unfiltered, int callingUid,
+            String callingPackage, boolean includeManagedNotVisible) {
+        // filter based on visibility.
+        Map<Account, Integer> firstPass = new HashMap<>();
+        for (Account account : unfiltered) {
+            int visibility =
+                    resolveAccountVisibility(account, callingUid, callingPackage, accounts);
+            if ((visibility == AccountManager.VISIBILITY_VISIBLE
+                    || visibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE)
+                    || (includeManagedNotVisible
+                            && (visibility
+                                    == AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE))) {
+                firstPass.put(account, visibility);
+            }
+        }
+        Map<Account, Integer> secondPass =
+                filterSharedAccounts(accounts, firstPass, callingUid, callingPackage);
+
+        Account[] filtered = new Account[secondPass.size()];
+        filtered = secondPass.keySet().toArray(filtered);
+        return filtered;
+    }
+
+    private Map<Account, Integer> filterSharedAccounts(UserAccounts userAccounts,
+            Map<Account, Integer> unfiltered, int callingUid, String callingPackage) {
+        // first part is to filter shared accounts.
+        // unfiltered type check is not necessary.
         if (getUserManager() == null || userAccounts == null || userAccounts.userId < 0
-                || callingUid == Process.myUid()) {
+                || callingUid == Process.SYSTEM_UID) {
             return unfiltered;
         }
         UserInfo user = getUserManager().getUserInfo(userAccounts.userId);
         if (user != null && user.isRestricted()) {
-            String[] packages = mPackageManager.getPackagesForUid(callingUid);
+            String[] packages =
+                    mPackageManager.getPackagesForUid(callingUid);
             // If any of the packages is a visible listed package, return the full set,
             // otherwise return non-shared accounts only.
             // This might be a temporary way to specify a visible list
@@ -4948,9 +5347,10 @@
                     return unfiltered;
                 }
             }
-            ArrayList<Account> allowed = new ArrayList<>();
             Account[] sharedAccounts = getSharedAccountsAsUser(userAccounts.userId);
-            if (sharedAccounts == null || sharedAccounts.length == 0) return unfiltered;
+            if (ArrayUtils.isEmpty(sharedAccounts)) {
+                return unfiltered;
+            }
             String requiredAccountType = "";
             try {
                 // If there's an explicit callingPackage specified, check if that package
@@ -4970,11 +5370,14 @@
                         }
                     }
                 }
-            } catch (NameNotFoundException nnfe) {
+            } catch (NameNotFoundException e) {
+                Log.d(TAG, "Package not found " + e.getMessage());
             }
-            for (Account account : unfiltered) {
+            Map<Account, Integer> filtered = new HashMap<>();
+            for (Map.Entry<Account, Integer> entry : unfiltered.entrySet()) {
+                Account account = entry.getKey();
                 if (account.type.equals(requiredAccountType)) {
-                    allowed.add(account);
+                    filtered.put(account, entry.getValue());
                 } else {
                     boolean found = false;
                     for (Account shared : sharedAccounts) {
@@ -4984,12 +5387,10 @@
                         }
                     }
                     if (!found) {
-                        allowed.add(account);
+                        filtered.put(account, entry.getValue());
                     }
                 }
             }
-            Account[] filtered = new Account[allowed.size()];
-            allowed.toArray(filtered);
             return filtered;
         } else {
             return unfiltered;
@@ -5001,14 +5402,14 @@
      * that the package is not allowed to access.
      */
     protected Account[] getAccountsFromCacheLocked(UserAccounts userAccounts, String accountType,
-            int callingUid, String callingPackage) {
+            int callingUid, String callingPackage, boolean includeManagedNotVisible) {
         if (accountType != null) {
             final Account[] accounts = userAccounts.accountCache.get(accountType);
             if (accounts == null) {
                 return EMPTY_ACCOUNT_ARRAY;
             } else {
-                return filterSharedAccounts(userAccounts, Arrays.copyOf(accounts, accounts.length),
-                        callingUid, callingPackage);
+                return filterAccounts(userAccounts, Arrays.copyOf(accounts, accounts.length),
+                        callingUid, callingPackage, includeManagedNotVisible);
             }
         } else {
             int totalLength = 0;
@@ -5025,7 +5426,8 @@
                         accountsOfType.length);
                 totalLength += accountsOfType.length;
             }
-            return filterSharedAccounts(userAccounts, accounts, callingUid, callingPackage);
+            return filterAccounts(userAccounts, accounts, callingUid, callingPackage,
+                    includeManagedNotVisible);
         }
     }
 
@@ -5253,19 +5655,21 @@
             if (userId == 0) {
                 // Migrate old file, if it exists, to the new location.
                 // Make sure the new file doesn't already exist. A dummy file could have been
-                // accidentally created in the old location, causing the new one to become corrupted
-                // as well.
+                // accidentally created in the old location,
+                // causing the new one to become corrupted as well.
                 File oldFile = new File(systemDir, PRE_N_DATABASE_NAME);
                 if (oldFile.exists() && !databaseFile.exists()) {
                     // Check for use directory; create if it doesn't exist, else renameTo will fail
                     File userDir = Environment.getUserSystemDirectory(userId);
                     if (!userDir.exists()) {
                         if (!userDir.mkdirs()) {
-                            throw new IllegalStateException("User dir cannot be created: " + userDir);
+                            throw new IllegalStateException(
+                                    "User dir cannot be created: " + userDir);
                         }
                     }
                     if (!oldFile.renameTo(databaseFile)) {
-                        throw new IllegalStateException("User dir cannot be migrated: " + databaseFile);
+                        throw new IllegalStateException(
+                                "User dir cannot be migrated: " + databaseFile);
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/accounts/AccountsDb.java b/services/core/java/com/android/server/accounts/AccountsDb.java
index 5ca74711..85e4b5f 100644
--- a/services/core/java/com/android/server/accounts/AccountsDb.java
+++ b/services/core/java/com/android/server/accounts/AccountsDb.java
@@ -355,7 +355,7 @@
     boolean deleteAuthtokensByAccountIdAndType(long accountId, String authtokenType) {
         SQLiteDatabase db = mDeDatabase.getWritableDatabaseUserIsUnlocked();
         return db.delete(CE_TABLE_AUTHTOKENS,
-                AUTHTOKENS_ACCOUNTS_ID + "=?" + accountId + " AND " + AUTHTOKENS_TYPE + "=?",
+                AUTHTOKENS_ACCOUNTS_ID + "=?" + " AND " + AUTHTOKENS_TYPE + "=?",
                 new String[]{String.valueOf(accountId), authtokenType}) > 0;
     }
 
@@ -946,12 +946,13 @@
     /**
      * Returns a map from uid to visibility value.
      */
-    Map<Integer, Integer> findAccountVisibilityForAccountId(long accountId) {
+    Map<Integer, Integer> findAllVisibilityValuesForAccount(Account account) {
         SQLiteDatabase db = mDeDatabase.getReadableDatabase();
         Map<Integer, Integer> result = new HashMap<>();
-        final Cursor cursor = db.query(TABLE_VISIBILITY,
-                new String[] {VISIBILITY_UID, VISIBILITY_VALUE}, VISIBILITY_ACCOUNTS_ID + "=? ",
-                new String[] {String.valueOf(accountId)}, null, null, null);
+        final Cursor cursor =
+                db.query(TABLE_VISIBILITY, new String[] {VISIBILITY_UID, VISIBILITY_VALUE},
+                        SELECTION_ACCOUNTS_ID_BY_ACCOUNT,
+                        new String[] {account.name, account.type}, null, null, null);
         try {
             while (cursor.moveToNext()) {
                 result.put(cursor.getInt(0), cursor.getInt(1));
@@ -1306,4 +1307,4 @@
         return new AccountsDb(deDatabaseHelper, context, preNDatabaseFile);
     }
 
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
new file mode 100644
index 0000000..3c90f93
--- /dev/null
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -0,0 +1,157 @@
+/*
+ * 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.server.am;
+
+import android.content.ContentResolver;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.util.KeyValueListParser;
+import android.util.Slog;
+
+import java.io.PrintWriter;
+
+/**
+ * Settings constants that can modify the activity manager's behavior.
+ */
+final class ActivityManagerConstants extends ContentObserver {
+    // Key names stored in the settings value.
+    private static final String KEY_ENFORCE_BG_CHECK = "enforce_bg_check";
+    private static final String KEY_MAX_CACHED_PROCESSES = "max_cached_processes";
+
+    private static final boolean DEFAULT_ENFORCE_BG_CHECK = SystemProperties.getBoolean(
+            "debug.bgcheck", false);
+    private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;
+
+    // Enforce background check on apps targeting O?
+    public boolean ENFORCE_BG_CHECK = DEFAULT_ENFORCE_BG_CHECK;
+
+    // Maximum number of cached processes we will allow.
+    public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;
+
+    private final ActivityManagerService mService;
+    private ContentResolver mResolver;
+    private final KeyValueListParser mParser = new KeyValueListParser(',');
+
+    private int mOverrideMaxCachedProcesses = -1;
+
+    // The maximum number of cached processes we will keep around before killing them.
+    // NOTE: this constant is *only* a control to not let us go too crazy with
+    // keeping around processes on devices with large amounts of RAM.  For devices that
+    // are tighter on RAM, the out of memory killer is responsible for killing background
+    // processes as RAM is needed, and we should *never* be relying on this limit to
+    // kill them.  Also note that this limit only applies to cached background processes;
+    // we have no limit on the number of service, visible, foreground, or other such
+    // processes and the number of those processes does not count against the cached
+    // process limit.
+    public int CUR_MAX_CACHED_PROCESSES;
+
+    // The maximum number of empty app processes we will let sit around.
+    public int CUR_MAX_EMPTY_PROCESSES;
+
+    // The number of empty apps at which we don't consider it necessary to do
+    // memory trimming.
+    public int CUR_TRIM_EMPTY_PROCESSES;
+
+    // The number of cached at which we don't consider it necessary to do
+    // memory trimming.
+    public int CUR_TRIM_CACHED_PROCESSES;
+
+    public ActivityManagerConstants(ActivityManagerService service, Handler handler) {
+        super(handler);
+        mService = service;
+        updateMaxCachedProcesses();
+    }
+
+    public void start(ContentResolver resolver) {
+        mResolver = resolver;
+        mResolver.registerContentObserver(Settings.Global.getUriFor(
+                Settings.Global.ACTIVITY_MANAGER_CONSTANTS), false, this);
+        updateConstants();
+    }
+
+    public void setOverrideMaxCachedProcesses(int value) {
+        mOverrideMaxCachedProcesses = value;
+        updateMaxCachedProcesses();
+    }
+
+    public int getOverrideMaxCachedProcesses() {
+        return mOverrideMaxCachedProcesses;
+    }
+
+    public static int computeEmptyProcessLimit(int totalProcessLimit) {
+        return totalProcessLimit/2;
+    }
+
+    @Override
+    public void onChange(boolean selfChange, Uri uri) {
+        updateConstants();
+    }
+
+    private void updateConstants() {
+        synchronized (mService) {
+            try {
+                mParser.setString(Settings.Global.getString(mResolver,
+                        Settings.Global.ACTIVITY_MANAGER_CONSTANTS));
+            } catch (IllegalArgumentException e) {
+                // Failed to parse the settings string, log this and move on
+                // with defaults.
+                Slog.e("ActivityManagerConstants", "Bad activity manager config settings", e);
+            }
+
+            ENFORCE_BG_CHECK = mParser.getBoolean(KEY_ENFORCE_BG_CHECK, DEFAULT_ENFORCE_BG_CHECK);
+            MAX_CACHED_PROCESSES = mParser.getInt(KEY_MAX_CACHED_PROCESSES,
+                    DEFAULT_MAX_CACHED_PROCESSES);
+            updateMaxCachedProcesses();
+        }
+    }
+
+    private void updateMaxCachedProcesses() {
+        CUR_MAX_CACHED_PROCESSES = mOverrideMaxCachedProcesses < 0
+                ? MAX_CACHED_PROCESSES : mOverrideMaxCachedProcesses;
+        CUR_MAX_EMPTY_PROCESSES = computeEmptyProcessLimit(CUR_MAX_CACHED_PROCESSES);
+
+        // Note the trim levels do NOT depend on the override process limit, we want
+        // to consider the same level the point where we do trimming regardless of any
+        // additional enforced limit.
+        final int rawMaxEmptyProcesses = computeEmptyProcessLimit(MAX_CACHED_PROCESSES);
+        CUR_TRIM_EMPTY_PROCESSES = rawMaxEmptyProcesses/2;
+        CUR_TRIM_CACHED_PROCESSES = (MAX_CACHED_PROCESSES-rawMaxEmptyProcesses)/3;
+    }
+
+    void dump(PrintWriter pw) {
+        pw.println("ACTIVITY MANAGER SETTINGS (dumpsys activity settings) "
+                + Settings.Global.ACTIVITY_MANAGER_CONSTANTS + ":");
+
+        pw.print("  "); pw.print(KEY_ENFORCE_BG_CHECK); pw.print("=");
+        pw.println(ENFORCE_BG_CHECK);
+
+        pw.print("  "); pw.print(KEY_MAX_CACHED_PROCESSES); pw.print("=");
+        pw.println(MAX_CACHED_PROCESSES);
+
+        pw.println();
+        if (mOverrideMaxCachedProcesses >= 0) {
+            pw.print("  mOverrideMaxCachedProcesses="); pw.println(mOverrideMaxCachedProcesses);
+        }
+        pw.print("  CUR_MAX_CACHED_PROCESSES="); pw.println(CUR_MAX_CACHED_PROCESSES);
+        pw.print("  CUR_MAX_EMPTY_PROCESSES="); pw.println(CUR_MAX_EMPTY_PROCESSES);
+        pw.print("  CUR_TRIM_EMPTY_PROCESSES="); pw.println(CUR_TRIM_EMPTY_PROCESSES);
+        pw.print("  CUR_TRIM_CACHED_PROCESSES="); pw.println(CUR_TRIM_CACHED_PROCESSES);
+    }
+}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a5742c2..7731228 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -761,11 +761,6 @@
     ProcessRecord mHeavyWeightProcess = null;
 
     /**
-     * Are we enforcing background restrictions?
-     */
-    final boolean mEnforceBackgroundCheck;
-
-    /**
      * Non-persistent app uid whitelist for background restrictions
      */
     int[] mBackgroundUidWhitelist = new int[] {
@@ -1427,6 +1422,7 @@
     ParcelFileDescriptor mProfileFd;
     int mSamplingInterval = 0;
     boolean mAutoStopProfiler = false;
+    boolean mStreamingOutput = false;
     int mProfileType = 0;
     final ProcessMap<Pair<Long, String>> mMemWatchProcesses = new ProcessMap<>();
     String mMemWatchDumpProcName;
@@ -1515,9 +1511,6 @@
      */
     boolean mBooted = false;
 
-    int mProcessLimit = ProcessList.MAX_CACHED_APPS;
-    int mProcessLimitOverride = -1;
-
     WindowManagerService mWindowManager;
     final ActivityThread mSystemThread;
 
@@ -1639,6 +1632,8 @@
     final MainHandler mHandler;
     final UiHandler mUiHandler;
 
+    final ActivityManagerConstants mConstants;
+
     PackageManagerInternal mPackageManagerInt;
 
     // VoiceInteraction session ID that changes for each new request except when
@@ -2620,10 +2615,9 @@
         mPermissionReviewRequired = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_permissionReviewRequired);
 
-        mEnforceBackgroundCheck = SystemProperties.getBoolean("debug.bgcheck", false);
         mBackgroundLaunchBroadcasts = SystemConfig.getInstance().getAllowImplicitBroadcasts();
         if (DEBUG_BACKGROUND_CHECK) {
-            Slog.d(TAG, "Enforcing O+ bg restrictions: " + mEnforceBackgroundCheck);
+            Slog.d(TAG, "Enforcing O+ bg restrictions: " + mConstants.ENFORCE_BG_CHECK);
             StringBuilder sb = new StringBuilder(200);
             sb.append("  ");
             for (String a : mBackgroundLaunchBroadcasts) {
@@ -2639,6 +2633,8 @@
         mHandler = new MainHandler(mHandlerThread.getLooper());
         mUiHandler = new UiHandler();
 
+        mConstants = new ActivityManagerConstants(this, mHandler);
+
         /* static; one-time init here */
         if (sKillHandler == null) {
             sKillThread = new ServiceThread(TAG + ":kill",
@@ -3712,7 +3708,8 @@
             }
             int debugFlags = 0;
             if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
-                debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
+                debugFlags |= Zygote.DEBUG_ENABLE_JDWP;
+                debugFlags |= Zygote.DEBUG_JAVA_DEBUGGABLE;
                 // Also turn on CheckJNI for debuggable apps. It's quite
                 // awkward to turn on otherwise.
                 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
@@ -6565,12 +6562,14 @@
             ParcelFileDescriptor profileFd = null;
             int samplingInterval = 0;
             boolean profileAutoStop = false;
+            boolean profileStreamingOutput = false;
             if (mProfileApp != null && mProfileApp.equals(processName)) {
                 mProfileProc = app;
                 profileFile = mProfileFile;
                 profileFd = mProfileFd;
                 samplingInterval = mSamplingInterval;
                 profileAutoStop = mAutoStopProfiler;
+                profileStreamingOutput = mStreamingOutput;
             }
             boolean enableTrackAllocation = false;
             if (mTrackAllocationApp != null && mTrackAllocationApp.equals(processName)) {
@@ -6600,7 +6599,8 @@
                 profileFd = profileFd.dup();
             }
             ProfilerInfo profilerInfo = profileFile == null ? null
-                    : new ProfilerInfo(profileFile, profileFd, samplingInterval, profileAutoStop);
+                    : new ProfilerInfo(profileFile, profileFd, samplingInterval, profileAutoStop,
+                                       profileStreamingOutput);
 
             // We deprecated Build.SERIAL and only apps that target pre NMR1
             // SDK can see it. Since access to the serial is now behind a
@@ -7276,9 +7276,6 @@
 
     /**
      * Whitelists {@code targetUid} to temporarily bypass Power Save mode.
-     *
-     * <p>{@code callerUid} must be allowed to request such whitelist by calling
-     * {@link #addTempPowerSaveWhitelistGrantorUid(int)}.
      */
     void tempWhitelistAppForPowerSave(int callerPid, int callerUid, int targetUid, long duration) {
         if (DEBUG_WHITELISTS) {
@@ -7470,8 +7467,7 @@
         enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
                 "setProcessLimit()");
         synchronized (this) {
-            mProcessLimit = max < 0 ? ProcessList.MAX_CACHED_APPS : max;
-            mProcessLimitOverride = max;
+            mConstants.setOverrideMaxCachedProcesses(max);
         }
         trimApplications();
     }
@@ -7479,7 +7475,7 @@
     @Override
     public int getProcessLimit() {
         synchronized (this) {
-            return mProcessLimitOverride;
+            return mConstants.getOverrideMaxCachedProcesses();
         }
     }
 
@@ -8034,7 +8030,7 @@
     // Unified app-op and target sdk check
     int appRestrictedInBackgroundLocked(int uid, String packageName, int packageTargetSdk) {
         // Apps that target O+ are always subject to background check
-        if (mEnforceBackgroundCheck && packageTargetSdk >= Build.VERSION_CODES.O) {
+        if (mConstants.ENFORCE_BG_CHECK && packageTargetSdk >= Build.VERSION_CODES.O) {
             if (DEBUG_BACKGROUND_CHECK) {
                 Slog.i(TAG, "App " + uid + "/" + packageName + " targets O+, restricted");
             }
@@ -11559,6 +11555,7 @@
             mSystemThread.installSystemProviders(providers);
         }
 
+        mConstants.start(mContext.getContentResolver());
         mCoreSettingsObserver = new CoreSettingsObserver(this);
         mFontScaleSettingObserver = new FontScaleSettingObserver();
 
@@ -12058,12 +12055,12 @@
     }
 
     @Override
-    public void startConfirmDeviceCredentialIntent(Intent intent) {
+    public void startConfirmDeviceCredentialIntent(Intent intent, Bundle options) {
         enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "startConfirmDeviceCredentialIntent");
         synchronized (this) {
             final long ident = Binder.clearCallingIdentity();
             try {
-                mActivityStarter.startConfirmCredentialIntent(intent);
+                mActivityStarter.startConfirmCredentialIntent(intent, options);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -12202,6 +12199,7 @@
             mProfileFd = profilerInfo.profileFd;
             mSamplingInterval = profilerInfo.samplingInterval;
             mAutoStopProfiler = profilerInfo.autoStopProfiler;
+            mStreamingOutput = profilerInfo.streamingOutput;
             mProfileType = 0;
         }
     }
@@ -14493,6 +14491,10 @@
                 synchronized (this) {
                     dumpAssociationsLocked(fd, pw, args, opti, true, dumpClient, dumpPackage);
                 }
+            } else if ("settings".equals(cmd)) {
+                synchronized (this) {
+                    mConstants.dump(pw);
+                }
             } else if ("services".equals(cmd) || "s".equals(cmd)) {
                 if (dumpClient) {
                     ActiveServices.ServiceDumper dumper;
@@ -14533,6 +14535,11 @@
         } else if (dumpClient) {
             ActiveServices.ServiceDumper sdumper;
             synchronized (this) {
+                mConstants.dump(pw);
+                pw.println();
+                if (dumpAll) {
+                    pw.println("-------------------------------------------------------------------------------");
+                }
                 dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
                 pw.println();
                 if (dumpAll) {
@@ -14591,6 +14598,11 @@
 
         } else {
             synchronized (this) {
+                mConstants.dump(pw);
+                pw.println();
+                if (dumpAll) {
+                    pw.println("-------------------------------------------------------------------------------");
+                }
                 dumpPendingIntentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
                 pw.println();
                 if (dumpAll) {
@@ -15166,7 +15178,7 @@
                 pw.println("  mProfileApp=" + mProfileApp + " mProfileProc=" + mProfileProc);
                 pw.println("  mProfileFile=" + mProfileFile + " mProfileFd=" + mProfileFd);
                 pw.println("  mSamplingInterval=" + mSamplingInterval + " mAutoStopProfiler="
-                        + mAutoStopProfiler);
+                        + mAutoStopProfiler + " mStreamingOutput=" + mStreamingOutput);
                 pw.println("  mProfileType=" + mProfileType);
             }
         }
@@ -19592,10 +19604,15 @@
 
     /** Helper method that requests bounds from WM and applies them to stack. */
     private void resizeStackWithBoundsFromWindowManager(int stackId, boolean deferResume) {
-        final Rect newBounds = mStackSupervisor.getStack(stackId).getBoundsForNewConfiguration();
+        final Rect newStackBounds = new Rect();
+        final Rect newTempTaskBounds = new Rect();
+        mStackSupervisor.getStack(stackId).getBoundsForNewConfiguration(newStackBounds,
+                newTempTaskBounds);
         mStackSupervisor.resizeStackLocked(
-                stackId, newBounds, null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
-                false /* preserveWindows */, false /* allowResizeInDockedMode */, deferResume);
+                stackId, !newStackBounds.isEmpty() ? newStackBounds : null /* bounds */,
+                !newTempTaskBounds.isEmpty() ? newTempTaskBounds : null /* tempTaskBounds */,
+                null /* tempTaskInsetBounds */, false /* preserveWindows */,
+                false /* allowResizeInDockedMode */, deferResume);
     }
 
     /**
@@ -21392,17 +21409,8 @@
         mNewNumServiceProcs = 0;
         mNewNumAServiceProcs = 0;
 
-        final int emptyProcessLimit;
-        final int cachedProcessLimit;
-        if (mProcessLimit <= 0) {
-            emptyProcessLimit = cachedProcessLimit = 0;
-        } else if (mProcessLimit == 1) {
-            emptyProcessLimit = 1;
-            cachedProcessLimit = 0;
-        } else {
-            emptyProcessLimit = ProcessList.computeEmptyProcessLimit(mProcessLimit);
-            cachedProcessLimit = mProcessLimit - emptyProcessLimit;
-        }
+        final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES;
+        final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES - emptyProcessLimit;
 
         // Let's determine how many processes we have running vs.
         // how many slots we have for background processes; we may want
@@ -21510,7 +21518,7 @@
                         }
                         break;
                     case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
-                        if (numEmpty > ProcessList.TRIM_EMPTY_APPS
+                        if (numEmpty > mConstants.CUR_TRIM_EMPTY_PROCESSES
                                 && app.lastActivityTime < oldTime) {
                             app.kill("empty for "
                                     + ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime)
@@ -21563,8 +21571,8 @@
         // memory they want.
         final int numCachedAndEmpty = numCached + numEmpty;
         int memFactor;
-        if (numCached <= ProcessList.TRIM_CACHED_APPS
-                && numEmpty <= ProcessList.TRIM_EMPTY_APPS) {
+        if (numCached <= mConstants.CUR_TRIM_CACHED_PROCESSES
+                && numEmpty <= mConstants.CUR_TRIM_EMPTY_PROCESSES) {
             if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
                 memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
             } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
@@ -22024,6 +22032,7 @@
         mProfileFile = null;
         mProfileType = 0;
         mAutoStopProfiler = false;
+        mStreamingOutput = false;
         mSamplingInterval = 0;
     }
 
@@ -22595,6 +22604,13 @@
         }
 
         @Override
+        public IBinder getTopVisibleActivity(int uid) {
+            synchronized (ActivityManagerService.this) {
+                return mStackSupervisor.getTopVisibleActivity(uid);
+            }
+        }
+
+        @Override
         public void notifyDockedStackMinimizedChanged(boolean minimized) {
             synchronized (ActivityManagerService.this) {
                 mStackSupervisor.setDockedStackMinimized(minimized);
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 1a2a31b..8c34776 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -115,6 +115,7 @@
     private String mProfileFile;
     private int mSamplingInterval;
     private boolean mAutoStop;
+    private boolean mStreaming;   // Streaming the profiling output to a file.
     private int mDisplayId;
     private int mStackId;
 
@@ -256,6 +257,7 @@
         mProfileFile = null;
         mSamplingInterval = 0;
         mAutoStop = false;
+        mStreaming = false;
         mUserId = defUser;
         mDisplayId = INVALID_DISPLAY;
         mStackId = INVALID_STACK_ID;
@@ -277,6 +279,8 @@
                     mAutoStop = false;
                 } else if (opt.equals("--sampling")) {
                     mSamplingInterval = Integer.parseInt(getNextArgRequired());
+                } else if (opt.equals("--streaming")) {
+                    mStreaming = true;
                 } else if (opt.equals("-R")) {
                     mRepeat = Integer.parseInt(getNextArgRequired());
                 } else if (opt.equals("-S")) {
@@ -354,7 +358,8 @@
                 if (fd == null) {
                     return 1;
                 }
-                profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop);
+                profilerInfo = new ProfilerInfo(mProfileFile, fd, mSamplingInterval, mAutoStop,
+                                                mStreaming);
             }
 
             pw.println("Starting: " + intent);
@@ -659,6 +664,7 @@
         int userId = UserHandle.USER_CURRENT;
         int profileType = 0;
         mSamplingInterval = 0;
+        mStreaming = false;
 
         String process = null;
 
@@ -672,6 +678,8 @@
                     userId = UserHandle.parseUserArg(getNextArgRequired());
                 } else if (opt.equals("--wall")) {
                     wall = true;
+                } else if (opt.equals("--streaming")) {
+                    mStreaming = true;
                 } else if (opt.equals("--sampling")) {
                     mSamplingInterval = Integer.parseInt(getNextArgRequired());
                 } else {
@@ -716,7 +724,7 @@
             if (fd == null) {
                 return -1;
             }
-            profilerInfo = new ProfilerInfo(profileFile, fd, mSamplingInterval, false);
+            profilerInfo = new ProfilerInfo(profileFile, fd, mSamplingInterval, false, mStreaming);
         }
 
         try {
@@ -2406,6 +2414,7 @@
             pw.println("    provider [COMP_SPEC]: provider client-side state");
             pw.println("    s[ervices] [COMP_SPEC ...]: service state");
             pw.println("    as[sociations]: tracked app associations");
+            pw.println("    settings: currently applied config settings");
             pw.println("    service [COMP_SPEC]: service client-side state");
             pw.println("    package [PACKAGE_NAME]: all state related to given package");
             pw.println("    all: dump all activities");
@@ -2424,7 +2433,7 @@
             pw.println("  help");
             pw.println("      Print this help text.");
             pw.println("  start-activity [-D] [-N] [-W] [-P <FILE>] [--start-profiler <FILE>]");
-            pw.println("          [--sampling INTERVAL] [-R COUNT] [-S]");
+            pw.println("          [--sampling INTERVAL] [--streaming] [-R COUNT] [-S]");
             pw.println("          [--track-allocation] [--user <USER_ID> | current] <INTENT>");
             pw.println("      Start an Activity.  Options are:");
             pw.println("      -D: enable debugging");
@@ -2433,6 +2442,8 @@
             pw.println("      --start-profiler <FILE>: start profiler and send results to <FILE>");
             pw.println("      --sampling INTERVAL: use sample profiling with INTERVAL microseconds");
             pw.println("          between samples (use with --start-profiler)");
+            pw.println("      --streaming: stream the profiling output to the specified file");
+            pw.println("          (use with --start-profiler)");
             pw.println("      -P <FILE>: like above, but profiling stops when app goes idle");
             pw.println("      -R: repeat the activity launch <COUNT> times.  Prior to each repeat,");
             pw.println("          the top activity will be finished.");
@@ -2479,11 +2490,14 @@
             pw.println("      stop: stop tracing IPC transactions and dump the results to file.");
             pw.println("      --dump-file <FILE>: Specify the file the trace should be dumped to.");
             pw.println("  profile [start|stop] [--user <USER_ID> current] [--sampling INTERVAL]");
-            pw.println("          <PROCESS> <FILE>");
+            pw.println("          [--streaming] <PROCESS> <FILE>");
             pw.println("      Start and stop profiler on a process.  The given <PROCESS> argument");
             pw.println("        may be either a process name or pid.  Options are:");
             pw.println("      --user <USER_ID> | current: When supplying a process name,");
             pw.println("          specify user of process to profile; uses current user if not specified.");
+            pw.println("      --sampling INTERVAL: use sample profiling with INTERVAL microseconds");
+            pw.println("          between samples");
+            pw.println("      --streaming: stream the profiling output to the specified file");
             pw.println("  dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>");
             pw.println("      Dump the heap of a process.  The given <PROCESS> argument may");
             pw.println("        be either a process name or pid.  Options are:");
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 2a849b6..baf7772 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -729,7 +729,6 @@
         if (mWindowContainerController != null) {
             throw new IllegalArgumentException("Window container=" + mWindowContainerController
                     + " already created for r=" + this);
-
         }
 
         inHistory = true;
@@ -754,6 +753,26 @@
         mWindowContainerController = null;
     }
 
+    /**
+     * Reparents this activity into {@param newTask} at the provided {@param position}.  The caller
+     * should ensure that the {@param newTask} is not already the parent of this activity.
+     */
+    void reparent(TaskRecord newTask, int position, String reason) {
+        final TaskRecord prevTask = task;
+        if (prevTask == newTask) {
+            throw new IllegalArgumentException(reason + ": task=" + newTask
+                    + " is already the parent of r=" + this);
+        }
+
+        // Must reparent first in window manager
+        mWindowContainerController.reparent(newTask.getWindowContainerController(), position);
+
+        // Remove the activity from the old task and add it to the new task
+        prevTask.removeActivity(this);
+        setTask(newTask, null);
+        newTask.addActivityAtIndex(position, this);
+    }
+
     private boolean isHomeIntent(Intent intent) {
         return Intent.ACTION_MAIN.equals(intent.getAction())
                 && intent.hasCategory(Intent.CATEGORY_HOME)
@@ -1810,7 +1829,8 @@
         if (_taskDescription.getIconFilename() == null &&
                 (icon = _taskDescription.getIcon()) != null) {
             final String iconFilename = createImageFilename(createTime, task.taskId);
-            final File iconFile = new File(TaskPersister.getUserImagesDir(userId), iconFilename);
+            final File iconFile = new File(TaskPersister.getUserImagesDir(task.userId),
+                    iconFilename);
             final String iconFilePath = iconFile.getAbsolutePath();
             service.mRecentTasks.saveImage(icon, iconFilePath);
             _taskDescription.setIconFilename(iconFilePath);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 98b5835c..9ce7ae30 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -26,6 +26,8 @@
 import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
+
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_APP;
@@ -542,8 +544,10 @@
         mWindowContainerController.setPictureInPictureAspectRatio(aspectRatio);
     }
 
-    void getStackDockedModeBounds(Rect outBounds, boolean ignoreVisibility) {
-        mWindowContainerController.getStackDockedModeBounds(outBounds, ignoreVisibility);
+    void getStackDockedModeBounds(Rect outBounds, Rect outTempBounds, Rect outTempInsetBounds,
+            boolean ignoreVisibility) {
+        mWindowContainerController.getStackDockedModeBounds(outBounds, outTempBounds,
+                outTempInsetBounds, ignoreVisibility);
     }
 
     void prepareFreezingTaskBounds() {
@@ -562,8 +566,8 @@
         outBounds.setEmpty();
     }
 
-    Rect getBoundsForNewConfiguration() {
-        return mWindowContainerController.getBoundsForNewConfiguration();
+    void getBoundsForNewConfiguration(Rect outBounds, Rect outTempBounds) {
+        mWindowContainerController.getBoundsForNewConfiguration(outBounds, outTempBounds);
     }
 
     void positionChildWindowContainerAtTop(TaskRecord child) {
@@ -1882,6 +1886,12 @@
             if (isTop) {
                 mTopActivityOccludesKeyguard |= showWhenLocked;
             }
+
+            final boolean canShowWithKeyguard = canShowWithInsecureKeyguard()
+                    && mStackSupervisor.mKeyguardController.canDismissKeyguard();
+            if (canShowWithKeyguard) {
+                return true;
+            }
         }
         if (keyguardShowing) {
 
@@ -1897,6 +1907,22 @@
         }
     }
 
+    /**
+     * Check if the display to which this stack is attached has
+     * {@link Display#FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD} applied.
+     */
+    private boolean canShowWithInsecureKeyguard() {
+        final ActivityStackSupervisor.ActivityDisplay activityDisplay
+                = mActivityContainer.mActivityDisplay;
+        if (activityDisplay == null) {
+            throw new IllegalStateException("Stack is not attached to any display, stackId="
+                    + mStackId);
+        }
+
+        final int flags = activityDisplay.mDisplay.getFlags();
+        return (flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0;
+    }
+
     private void checkTranslucentActivityWaiting(ActivityRecord top) {
         if (mTranslucentActivityWaiting != top) {
             mUndrawnActivitiesBelowTopTranslucent.clear();
@@ -3043,8 +3069,7 @@
                             + " to task=" + task + ":" + taskInsertionPoint);
                     for (int srcPos = start; srcPos >= i; --srcPos) {
                         final ActivityRecord p = activities.get(srcPos);
-                        p.setTask(task, null);
-                        task.addActivityAtIndex(taskInsertionPoint, p);
+                        p.reparent(task, taskInsertionPoint, "resetAffinityTaskIfNeededLocked");
 
                         if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
                                 "Removing and adding activity " + p + " to stack at " + task
@@ -5071,12 +5096,17 @@
         final boolean wasResumed = wasFocused && (prevStack.mResumedActivity == r);
         final boolean wasPaused = prevStack.mPausingActivity == r;
 
+        // Create a new task for the activity to be parented in
         final TaskRecord task = createTaskRecord(
                 mStackSupervisor.getNextTaskIdForUserLocked(r.userId),
                 r.info, r.intent, null, null, true, r.mActivityType);
-        r.setTask(task, null);
-        task.addActivityToTop(r);
+        // This is a new task, so reparenting it to position 0 will move it to the top
+        r.reparent(task, 0 /* position */, "moveActivityToStack");
+
+        // Notify the task actiivties if it was moved to/from a pinned stack
         mStackSupervisor.scheduleReportPictureInPictureModeChangedIfNeeded(task, prevStack);
+
+        // Resume the activity if necessary after it has moved
         moveToFrontAndResumeStateIfNeeded(r, wasFocused, wasResumed, wasPaused,
                 "moveActivityToStack");
         if (wasResumed) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 29032f8..b2b3e61 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -418,8 +418,6 @@
 
     final ActivityMetricsLogger mActivityMetricsLogger;
 
-    private final ResizeDockedStackTimeout mResizeDockedStackTimeout;
-
     @Override
     protected int getChildCount() {
         return mActivityDisplays.size();
@@ -529,7 +527,6 @@
         mService = service;
         mHandler = new ActivityStackSupervisorHandler(mService.mHandler.getLooper());
         mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext);
-        mResizeDockedStackTimeout = new ResizeDockedStackTimeout(service, this, mHandler);
         mKeyguardController = new KeyguardController(service, this);
     }
 
@@ -1322,7 +1319,8 @@
                         }
 
                         profilerInfo = new ProfilerInfo(profileFile, profileFd,
-                                mService.mSamplingInterval, mService.mAutoStopProfiler);
+                                mService.mSamplingInterval, mService.mAutoStopProfiler,
+                                mService.mStreamingOutput);
                     }
                 }
             }
@@ -2346,13 +2344,19 @@
                 // static stacks need to be adjusted so they don't overlap with the docked stack.
                 // We get the bounds to use from window manager which has been adjusted for any
                 // screen controls and is also the same for all stacks.
+                final Rect tempOtherTaskRect = new Rect();
+                final Rect tempOtherTaskInsetRect = new Rect();
                 for (int i = FIRST_STATIC_STACK_ID; i <= LAST_STATIC_STACK_ID; i++) {
                     final ActivityStack current = getStack(i);
                     if (current != null && StackId.isResizeableByDockedStack(i)) {
-                        current.getStackDockedModeBounds(tempRect, true /* ignoreVisibility */);
-                        resizeStackLocked(i, tempRect, tempOtherTaskBounds,
-                                tempOtherTaskInsetBounds, preserveWindows,
-                                true /* allowResizeInDockedMode */, deferResume);
+                        current.getStackDockedModeBounds(tempRect, tempOtherTaskRect,
+                                tempOtherTaskInsetRect, true /* ignoreVisibility */);
+                        resizeStackLocked(i, tempRect,
+                                !tempOtherTaskRect.isEmpty() ? tempOtherTaskRect :
+                                        tempOtherTaskBounds,
+                                !tempOtherTaskInsetRect.isEmpty() ? tempOtherTaskInsetRect :
+                                        tempOtherTaskInsetBounds,
+                                preserveWindows, true /* allowResizeInDockedMode */, deferResume);
                     }
                 }
             }
@@ -2364,12 +2368,6 @@
             mWindowManager.continueSurfaceLayout();
             Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
         }
-
-        mResizeDockedStackTimeout.notifyResizing(dockedBounds,
-                tempDockedTaskBounds != null
-                || tempDockedTaskInsetBounds != null
-                || tempOtherTaskBounds != null
-                || tempOtherTaskInsetBounds != null);
     }
 
     void resizePinnedStackLocked(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
@@ -4901,4 +4899,24 @@
         }
         return topActivityTokens;
     }
+
+    public IBinder getTopVisibleActivity(int uid) {
+        // TODO(b/33197203): get rid of DEFAULT_DISPLAY here?. Used in
+        // VoiceInteractionManagerServiceImpl#showSessionLocked.
+        final ActivityDisplay display = mActivityDisplays.get(DEFAULT_DISPLAY);
+        if (display == null) {
+            return null;
+        }
+        final ArrayList<ActivityStack> stacks = display.mStacks;
+        for (int i = stacks.size() - 1; i >= 0; i--) {
+            ActivityStack stack = stacks.get(i);
+            if (stack.getStackVisibilityLocked(null) == ActivityStack.STACK_VISIBLE) {
+                ActivityRecord top = stack.topActivity();
+                if (top != null && stack == mFocusedStack && top.app.uid == uid) {
+                    return top.appToken;
+                }
+            }
+        }
+        return null;
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index b913a23..96f732e 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -648,18 +648,18 @@
                     null);
             credential.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
             // Show confirm credentials activity.
-            startConfirmCredentialIntent(credential);
+            startConfirmCredentialIntent(credential, null);
         }
     }
 
-    void startConfirmCredentialIntent(Intent intent) {
+    void startConfirmCredentialIntent(Intent intent, Bundle optionsBundle) {
         intent.addFlags(FLAG_ACTIVITY_NEW_TASK |
                 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
                 FLAG_ACTIVITY_TASK_ON_HOME);
-        final ActivityOptions options = ActivityOptions.makeBasic();
+        ActivityOptions options = (optionsBundle != null ? new ActivityOptions(optionsBundle)
+                        : ActivityOptions.makeBasic());
         options.setLaunchTaskId(mSupervisor.getHomeActivity().task.taskId);
-        mService.mContext.startActivityAsUser(intent, options.toBundle(),
-                UserHandle.CURRENT);
+        mService.mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
     }
 
     final int startActivityMayWait(IApplicationThread caller, int callingUid,
@@ -2072,6 +2072,9 @@
             case RECENTS_STACK_ID:
                 return r.isRecentsActivity();
             default:
+                if (StackId.isDynamicStack(stackId)) {
+                    return true;
+                }
                 Slog.e(TAG, "isValidLaunchStackId: Unexpected stackId=" + stackId);
                 return false;
         }
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index b0a4746..2bd119e 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -280,7 +280,7 @@
     /**
      * @return true if Keyguard can be currently dismissed without entering credentials.
      */
-    private boolean canDismissKeyguard() {
+    boolean canDismissKeyguard() {
         return mWindowManager.isKeyguardTrusted() || !mWindowManager.isKeyguardSecure();
     }
 
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 1322ecf..40effff 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -138,31 +138,9 @@
     // without empty apps being able to push them out of memory.
     static final int MIN_CACHED_APPS = 2;
 
-    // The maximum number of cached processes we will keep around before killing them.
-    // NOTE: this constant is *only* a control to not let us go too crazy with
-    // keeping around processes on devices with large amounts of RAM.  For devices that
-    // are tighter on RAM, the out of memory killer is responsible for killing background
-    // processes as RAM is needed, and we should *never* be relying on this limit to
-    // kill them.  Also note that this limit only applies to cached background processes;
-    // we have no limit on the number of service, visible, foreground, or other such
-    // processes and the number of those processes does not count against the cached
-    // process limit.
-    static final int MAX_CACHED_APPS = 32;
-
     // We allow empty processes to stick around for at most 30 minutes.
     static final long MAX_EMPTY_TIME = 30*60*1000;
 
-    // The maximum number of empty app processes we will let sit around.
-    private static final int MAX_EMPTY_APPS = computeEmptyProcessLimit(MAX_CACHED_APPS);
-
-    // The number of empty apps at which we don't consider it necessary to do
-    // memory trimming.
-    static final int TRIM_EMPTY_APPS = MAX_EMPTY_APPS/2;
-
-    // The number of cached at which we don't consider it necessary to do
-    // memory trimming.
-    static final int TRIM_CACHED_APPS = (MAX_CACHED_APPS-MAX_EMPTY_APPS)/3;
-
     // Threshold of number of cached+empty where we consider memory critical.
     static final int TRIM_CRITICAL_THRESHOLD = 3;
 
diff --git a/services/core/java/com/android/server/am/ResizeDockedStackTimeout.java b/services/core/java/com/android/server/am/ResizeDockedStackTimeout.java
deleted file mode 100644
index ff39589..0000000
--- a/services/core/java/com/android/server/am/ResizeDockedStackTimeout.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.am;
-
-import android.graphics.Rect;
-import android.os.Handler;
-
-import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
-
-/**
- * When resizing the docked stack, a caller can temporarily supply task bounds that are different
- * from the stack bounds. In order to return to a sane state if the caller crashes or has a bug,
- * this class manages this cycle.
- */
-class ResizeDockedStackTimeout {
-
-    private static final long TIMEOUT_MS = 10 * 1000;
-    private final ActivityManagerService mService;
-    private final ActivityStackSupervisor mSupervisor;
-    private final Handler mHandler;
-    private final Rect mCurrentDockedBounds = new Rect();
-
-    private final Runnable mTimeoutRunnable = new Runnable() {
-        @Override
-        public void run() {
-            synchronized (mService) {
-                mSupervisor.resizeDockedStackLocked(mCurrentDockedBounds, null, null, null, null,
-                        PRESERVE_WINDOWS);
-            }
-        }
-    };
-
-    ResizeDockedStackTimeout(ActivityManagerService service, ActivityStackSupervisor supervisor,
-            Handler handler) {
-        mService = service;
-        mSupervisor = supervisor;
-        mHandler = handler;
-    }
-
-    void notifyResizing(Rect dockedBounds, boolean hasTempBounds) {
-        mHandler.removeCallbacks(mTimeoutRunnable);
-        if (!hasTempBounds) {
-            return;
-        }
-        mCurrentDockedBounds.set(dockedBounds);
-        mHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MS);
-    }
-
-}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index f12d7b7..fef4073 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -1028,8 +1028,10 @@
         addActivityAtIndex(mActivities.size(), r);
     }
 
-    // TODO: Figure-out if any of the call points expect the window container to be reparented and
-    // correct them to use the right method.
+    /**
+     * Adds an activity {@param r} at the given {@param index}. The activity {@param r} must either
+     * be in the current task or unparented to any task.
+     */
     void addActivityAtIndex(int index, ActivityRecord r) {
         // Remove r first, and if it wasn't already in the list and it's fullscreen, count it.
         if (!mActivities.remove(r) && r.fullscreen) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 31ef94f..213041e 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -144,7 +144,6 @@
  */
 public class AudioService extends IAudioService.Stub
         implements AccessibilityManager.TouchExplorationStateChangeListener,
-            AccessibilityManager.AccessibilityStateChangeListener,
             AccessibilityManager.AccessibilityServicesStateChangeListener {
 
     private static final String TAG = "AudioService";
@@ -5926,25 +5925,13 @@
     //==========================================================================================
     // Accessibility
 
-    /**
-     * Compile-time constant to enable the use of an independent a11y volume:
-     * - set to true to listen to a11y services state changes and read
-     *   the whether any exposes the FLAG_ENABLE_ACCESSIBILITY_VOLUME flag
-     * - set to false to listen to when accessibility services are started (e.g. "TalkBack started")
-     */
-    private static final boolean USE_FLAG_ENABLE_ACCESSIBILITY_VOLUME = false;
-
     private void initA11yMonitoring() {
         final AccessibilityManager accessibilityManager =
                 (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
         updateDefaultStreamOverrideDelay(accessibilityManager.isTouchExplorationEnabled());
         updateA11yVolumeAlias(accessibilityManager.isEnabled());
         accessibilityManager.addTouchExplorationStateChangeListener(this);
-        if (USE_FLAG_ENABLE_ACCESSIBILITY_VOLUME) {
-            accessibilityManager.addAccessibilityServicesStateChangeListener(this);
-        } else {
-            accessibilityManager.addAccessibilityStateChangeListener(this);
-        }
+        accessibilityManager.addAccessibilityServicesStateChangeListener(this);
     }
 
     //---------------------------------------------------------------------------------
@@ -5982,12 +5969,6 @@
 
     private static boolean sIndependentA11yVolume = false;
 
-    // implementation of AccessibilityStateChangeListener
-    @Override
-    public void onAccessibilityStateChanged(boolean enabled) {
-        updateA11yVolumeAlias(enabled);
-    }
-
     // implementation of AccessibilityServicesStateChangeListener
     @Override
     public void onAccessibilityServicesStateChanged() {
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 8d4f0a9..5fed397 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -40,6 +40,7 @@
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Slog;
@@ -50,18 +51,106 @@
 import java.util.HashSet;
 import java.util.List;
 
+import java.lang.Thread;
+import java.lang.Runnable;
+import java.lang.InterruptedException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+// The following class is Android Emulator specific. It is used to read and
+// write contents of the host system's clipboard.
+class HostClipboardMonitor implements Runnable {
+    public interface HostClipboardCallback {
+        void onHostClipboardUpdated(String contents);
+    }
+
+    private RandomAccessFile mPipe = null;
+    private HostClipboardCallback mHostClipboardCallback;
+    private static final String PIPE_NAME = "pipe:clipboard";
+    private static final String PIPE_DEVICE = "/dev/qemu_pipe";
+
+    private void openPipe() {
+        try {
+            // String.getBytes doesn't include the null terminator,
+            // but the QEMU pipe device requires the pipe service name
+            // to be null-terminated.
+            byte[] b = new byte[PIPE_NAME.length() + 1];
+            b[PIPE_NAME.length()] = 0;
+            System.arraycopy(
+                PIPE_NAME.getBytes(),
+                0,
+                b,
+                0,
+                PIPE_NAME.length());
+            mPipe = new RandomAccessFile(PIPE_DEVICE, "rw");
+            mPipe.write(b);
+        } catch (IOException e) {
+            try {
+                if (mPipe != null) mPipe.close();
+            } catch (IOException ee) {}
+            mPipe = null;
+        }
+    }
+
+    public HostClipboardMonitor(HostClipboardCallback cb) {
+        mHostClipboardCallback = cb;
+    }
+
+    @Override
+    public void run() {
+        while(!Thread.interrupted()) {
+            try {
+                // There's no guarantee that QEMU pipes will be ready at the moment
+                // this method is invoked. We simply try to get the pipe open and
+                // retry on failure indefinitely.
+                while (mPipe == null) {
+                    openPipe();
+                    Thread.sleep(100);
+                }
+                int size = mPipe.readInt();
+                size = Integer.reverseBytes(size);
+                byte[] receivedData = new byte[size];
+                mPipe.readFully(receivedData);
+                mHostClipboardCallback.onHostClipboardUpdated(
+                    new String(receivedData));
+            } catch (IOException e) {
+                try {
+                    mPipe.close();
+                } catch (IOException ee) {}
+                mPipe = null;
+            } catch (InterruptedException e) {}
+        }
+    }
+
+    public void setHostClipboard(String content) {
+        try {
+            if (mPipe != null) {
+                mPipe.writeInt(Integer.reverseBytes(content.getBytes().length));
+                mPipe.write(content.getBytes());
+            }
+        } catch(IOException e) {
+            Slog.e("HostClipboardMonitor",
+                   "Failed to set host clipboard " + e.getMessage());
+        }
+    }
+}
+
 /**
  * Implementation of the clipboard for copy and paste.
  */
 public class ClipboardService extends SystemService {
 
     private static final String TAG = "ClipboardService";
+    private static final boolean IS_EMULATOR =
+        SystemProperties.getBoolean("ro.kernel.qemu", false);
 
     private final IActivityManager mAm;
     private final IUserManager mUm;
     private final PackageManager mPm;
     private final AppOpsManager mAppOps;
     private final IBinder mPermissionOwner;
+    private HostClipboardMonitor mHostClipboardMonitor = null;
+    private Thread mHostMonitorThread = null;
 
     private final SparseArray<PerUserClipboard> mClipboards = new SparseArray<>();
 
@@ -82,6 +171,23 @@
             Slog.w("clipboard", "AM dead", e);
         }
         mPermissionOwner = permOwner;
+        if (IS_EMULATOR) {
+            mHostClipboardMonitor = new HostClipboardMonitor(
+                new HostClipboardMonitor.HostClipboardCallback() {
+                    @Override
+                    public void onHostClipboardUpdated(String contents){
+                        ClipData clip =
+                            new ClipData("host clipboard",
+                                         new String[]{"text/plain"},
+                                         new ClipData.Item(contents));
+                        synchronized(mClipboards) {
+                            setPrimaryClipInternal(getClipboard(0), clip);
+                        }
+                    }
+                });
+            mHostMonitorThread = new Thread(mHostClipboardMonitor);
+            mHostMonitorThread.start();
+        }
     }
 
     @Override
@@ -142,6 +248,11 @@
                 if (clip != null && clip.getItemCount() <= 0) {
                     throw new IllegalArgumentException("No items");
                 }
+                if (clip.getItemAt(0).getText() != null &&
+                    mHostClipboardMonitor != null) {
+                    mHostClipboardMonitor.setHostClipboard(
+                        clip.getItemAt(0).getText().toString());
+                }
                 final int callingUid = Binder.getCallingUid();
                 if (mAppOps.noteOp(AppOpsManager.OP_WRITE_CLIPBOARD, callingUid,
                         callingPackage) != AppOpsManager.MODE_ALLOWED) {
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index b0e4509..9d63462 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -1244,10 +1244,6 @@
                 return false;
             }
 
-            private boolean isSimCardAbsent(String state) {
-                return IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(state);
-            }
-
             private boolean isSimCardLoaded(String state) {
                 return IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state);
             }
@@ -1264,9 +1260,8 @@
                 // used to verify this receiver is still current
                 final private int mGenerationNumber;
 
-                // we're interested in edge-triggered LOADED notifications, so
-                // ignore LOADED unless we saw an ABSENT state first
-                private boolean mSimAbsentSeen = false;
+                // used to check the sim state transition from non-loaded to loaded
+                private boolean mSimNotLoadedSeen = false;
 
                 public SimChangeBroadcastReceiver(int generationNumber) {
                     mGenerationNumber = generationNumber;
@@ -1284,16 +1279,16 @@
 
                     final String state = intent.getStringExtra(
                             IccCardConstants.INTENT_KEY_ICC_STATE);
-                    Log.d(TAG, "got Sim changed to state " + state + ", mSimAbsentSeen=" +
-                            mSimAbsentSeen);
+                    Log.d(TAG, "got Sim changed to state " + state + ", mSimNotLoadedSeen=" +
+                            mSimNotLoadedSeen);
 
-                    if (isSimCardAbsent(state)) {
-                        if (!mSimAbsentSeen) mSimAbsentSeen = true;
+                    if (!isSimCardLoaded(state)) {
+                        if (!mSimNotLoadedSeen) mSimNotLoadedSeen = true;
                         return;
                     }
 
-                    if (isSimCardLoaded(state) && mSimAbsentSeen) {
-                        mSimAbsentSeen = false;
+                    if (isSimCardLoaded(state) && mSimNotLoadedSeen) {
+                        mSimNotLoadedSeen = false;
 
                         if (!hasMobileHotspotProvisionApp()) return;
 
diff --git a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
index 23481dc..08a3332 100644
--- a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
@@ -40,7 +40,9 @@
  * pertaining to the current and any potential upstream network.
  *
  * Calling #start() registers two callbacks: one to track the system default
- * network and a second to specifically observe TYPE_MOBILE_DUN networks.
+ * network and a second to observe all networks.  The latter is necessary
+ * while the expression of preferred upstreams remains a list of legacy
+ * connectivity types.  In future, this can be revisited.
  *
  * The methods and data members of this class are only to be accessed and
  * modified from the tethering master state machine thread. Any other
@@ -48,6 +50,10 @@
  *
  * TODO: Move upstream selection logic here.
  *
+ * All callback methods are run on the same thread as the specified target
+ * state machine.  This class does not require locking when accessed from this
+ * thread.  Access from other threads is not advised.
+ *
  * @hide
  */
 public class UpstreamNetworkMonitor {
@@ -60,15 +66,20 @@
     public static final int EVENT_ON_LINKPROPERTIES = 3;
     public static final int EVENT_ON_LOST           = 4;
 
+    private static final int LISTEN_ALL = 1;
+    private static final int TRACK_DEFAULT = 2;
+    private static final int MOBILE_REQUEST = 3;
+
     private final Context mContext;
     private final StateMachine mTarget;
     private final int mWhat;
     private final HashMap<Network, NetworkState> mNetworkMap = new HashMap<>();
     private ConnectivityManager mCM;
+    private NetworkCallback mListenAllCallback;
     private NetworkCallback mDefaultNetworkCallback;
-    private NetworkCallback mDunTetheringCallback;
     private NetworkCallback mMobileNetworkCallback;
     private boolean mDunRequired;
+    private Network mCurrentDefault;
 
     public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, int what) {
         mContext = ctx;
@@ -85,16 +96,13 @@
     public void start() {
         stop();
 
-        mDefaultNetworkCallback = new UpstreamNetworkCallback();
-        cm().registerDefaultNetworkCallback(mDefaultNetworkCallback);
+        final NetworkRequest listenAllRequest = new NetworkRequest.Builder()
+                .clearCapabilities().build();
+        mListenAllCallback = new UpstreamNetworkCallback(LISTEN_ALL);
+        cm().registerNetworkCallback(listenAllRequest, mListenAllCallback);
 
-        final NetworkRequest dunTetheringRequest = new NetworkRequest.Builder()
-                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
-                .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
-                .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
-                .build();
-        mDunTetheringCallback = new UpstreamNetworkCallback();
-        cm().registerNetworkCallback(dunTetheringRequest, mDunTetheringCallback);
+        mDefaultNetworkCallback = new UpstreamNetworkCallback(TRACK_DEFAULT);
+        cm().registerDefaultNetworkCallback(mDefaultNetworkCallback);
     }
 
     public void stop() {
@@ -103,8 +111,8 @@
         releaseCallback(mDefaultNetworkCallback);
         mDefaultNetworkCallback = null;
 
-        releaseCallback(mDunTetheringCallback);
-        mDunTetheringCallback = null;
+        releaseCallback(mListenAllCallback);
+        mListenAllCallback = null;
 
         mNetworkMap.clear();
     }
@@ -140,7 +148,7 @@
 
         // The existing default network and DUN callbacks will be notified.
         // Therefore, to avoid duplicate notifications, we only register a no-op.
-        mMobileNetworkCallback = new NetworkCallback();
+        mMobileNetworkCallback = new UpstreamNetworkCallback(MOBILE_REQUEST);
 
         // TODO: Change the timeout from 0 (no onUnavailable callback) to some
         // moderate callback timeout. This might be useful for updating some UI.
@@ -165,86 +173,117 @@
         return (network != null) ? mNetworkMap.get(network) : null;
     }
 
-    private void handleAvailable(Network network) {
-        if (VDBG) {
-            Log.d(TAG, "EVENT_ON_AVAILABLE for " + network);
-        }
+    private void handleAvailable(int callbackType, Network network) {
+        if (VDBG) Log.d(TAG, "EVENT_ON_AVAILABLE for " + network);
+
         if (!mNetworkMap.containsKey(network)) {
             mNetworkMap.put(network,
                     new NetworkState(null, null, null, network, null, null));
         }
 
-        final ConnectivityManager cm = cm();
-
-        if (mDefaultNetworkCallback != null) {
+        // Always request whatever extra information we can, in case this
+        // was already up when start() was called, in which case we would
+        // not have been notified of any information that had not changed.
+        final NetworkCallback cb =
+                (callbackType == TRACK_DEFAULT) ? mDefaultNetworkCallback :
+                (callbackType == MOBILE_REQUEST) ? mMobileNetworkCallback : null;
+        if (cb != null) {
+            final ConnectivityManager cm = cm();
             cm.requestNetworkCapabilities(mDefaultNetworkCallback);
             cm.requestLinkProperties(mDefaultNetworkCallback);
         }
 
-        // Requesting updates for mDunTetheringCallback is not
-        // necessary. Because it's a listen, it will already have
-        // heard all NetworkCapabilities and LinkProperties updates
-        // since UpstreamNetworkMonitor was started. Because we
-        // start UpstreamNetworkMonitor before chooseUpstreamType()
-        // is ever invoked (it can register a DUN request) this is
-        // mostly safe. However, if a DUN network is already up for
-        // some reason (unlikely, because DUN is restricted and,
-        // unless the DUN network is shared with another APN, only
-        // the system can request it and this is the only part of
-        // the system that requests it) we won't know its
-        // LinkProperties or NetworkCapabilities.
+        if (callbackType == TRACK_DEFAULT) {
+            mCurrentDefault = network;
+        }
 
+        // Requesting updates for mListenAllCallback is not currently possible
+        // because it's a "listen". Two possible solutions to getting updates
+        // about networks without waiting for a change (which might never come)
+        // are:
+        //
+        //     [1] extend request{NetworkCapabilities,LinkProperties}() to
+        //         take a Network argument and have ConnectivityService do
+        //         what's required (if the network satisfies the request)
+        //
+        //     [2] explicitly file a NetworkRequest for each connectivity type
+        //         listed as a preferred upstream and wait for these callbacks
+        //         to be notified (requires tracking many more callbacks).
+        //
+        // Until this is addressed, networks that exist prior to the "listen"
+        // registration and which do not subsequently change will not cause
+        // us to learn their NetworkCapabilities nor their LinkProperties.
+
+        // TODO: If sufficient information is available to select a more
+        // preferable upstream, do so now and notify the target.
         notifyTarget(EVENT_ON_AVAILABLE, network);
     }
 
     private void handleNetCap(Network network, NetworkCapabilities newNc) {
-        if (!mNetworkMap.containsKey(network)) {
-            // Ignore updates for networks for which we have not yet
-            // received onAvailable() - which should never happen -
-            // or for which we have already received onLost().
+        final NetworkState prev = mNetworkMap.get(network);
+        if (prev == null || newNc.equals(prev.networkCapabilities)) {
+            // Ignore notifications about networks for which we have not yet
+            // received onAvailable() (should never happen) and any duplicate
+            // notifications (e.g. matching more than one of our callbacks).
             return;
         }
+
         if (VDBG) {
             Log.d(TAG, String.format("EVENT_ON_CAPABILITIES for %s: %s",
                     network, newNc));
         }
 
-        final NetworkState prev = mNetworkMap.get(network);
-        mNetworkMap.put(network,
-                new NetworkState(null, prev.linkProperties, newNc,
-                                 network, null, null));
+        mNetworkMap.put(network, new NetworkState(
+                null, prev.linkProperties, newNc, network, null, null));
+        // TODO: If sufficient information is available to select a more
+        // preferable upstream, do so now and notify the target.
         notifyTarget(EVENT_ON_CAPABILITIES, network);
     }
 
     private void handleLinkProp(Network network, LinkProperties newLp) {
-        if (!mNetworkMap.containsKey(network)) {
-            // Ignore updates for networks for which we have not yet
-            // received onAvailable() - which should never happen -
-            // or for which we have already received onLost().
+        final NetworkState prev = mNetworkMap.get(network);
+        if (prev == null || newLp.equals(prev.linkProperties)) {
+            // Ignore notifications about networks for which we have not yet
+            // received onAvailable() (should never happen) and any duplicate
+            // notifications (e.g. matching more than one of our callbacks).
             return;
         }
+
         if (VDBG) {
             Log.d(TAG, String.format("EVENT_ON_LINKPROPERTIES for %s: %s",
                     network, newLp));
         }
 
-        final NetworkState prev = mNetworkMap.get(network);
-        mNetworkMap.put(network,
-                new NetworkState(null, newLp, prev.networkCapabilities,
-                                 network, null, null));
+        mNetworkMap.put(network, new NetworkState(
+                null, newLp, prev.networkCapabilities, network, null, null));
+        // TODO: If sufficient information is available to select a more
+        // preferable upstream, do so now and notify the target.
         notifyTarget(EVENT_ON_LINKPROPERTIES, network);
     }
 
-    private void handleLost(Network network) {
-        if (!mNetworkMap.containsKey(network)) {
-            // Ignore updates for networks for which we have not yet
-            // received onAvailable() - which should never happen -
-            // or for which we have already received onLost().
+    private void handleLost(int callbackType, Network network) {
+        if (callbackType == TRACK_DEFAULT) {
+            mCurrentDefault = null;
+            // Receiving onLost() for a default network does not necessarily
+            // mean the network is gone.  We wait for a separate notification
+            // on either the LISTEN_ALL or MOBILE_REQUEST callbacks before
+            // clearing all state.
             return;
         }
-        if (VDBG) {
-            Log.d(TAG, "EVENT_ON_LOST for " + network);
+
+        if (!mNetworkMap.containsKey(network)) {
+            // Ignore loss of networks about which we had not previously
+            // learned any information or for which we have already processed
+            // an onLost() notification.
+            return;
         }
+
+        if (VDBG) Log.d(TAG, "EVENT_ON_LOST for " + network);
+
+        // TODO: If sufficient information is available to select a more
+        // preferable upstream, do so now and notify the target.  Likewise,
+        // if the current upstream network is gone, notify the target of the
+        // fact that we now have no upstream at all.
         notifyTarget(EVENT_ON_LOST, mNetworkMap.remove(network));
     }
 
@@ -261,9 +300,15 @@
      * tethering master state machine thread for subsequent processing.
      */
     private class UpstreamNetworkCallback extends NetworkCallback {
+        private final int mCallbackType;
+
+        UpstreamNetworkCallback(int callbackType) {
+            mCallbackType = callbackType;
+        }
+
         @Override
         public void onAvailable(Network network) {
-            mTarget.getHandler().post(() -> handleAvailable(network));
+            mTarget.getHandler().post(() -> handleAvailable(mCallbackType, network));
         }
 
         @Override
@@ -278,7 +323,7 @@
 
         @Override
         public void onLost(Network network) {
-            mTarget.getHandler().post(() -> handleLost(network));
+            mTarget.getHandler().post(() -> handleLost(mCallbackType, network));
         }
     }
 
diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
index 6719182..4a52b3c 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
@@ -93,6 +93,11 @@
     public static final int FLAG_ROUND = 1 << 8;
 
     /**
+     * Flag: This display can show its content when non-secure keyguard is shown.
+     */
+    public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 9;
+
+    /**
      * Touch attachment: Display does not receive touch.
      */
     public static final int TOUCH_NONE = 0;
@@ -420,6 +425,9 @@
         if ((flags & FLAG_ROUND) != 0) {
             msg.append(", FLAG_ROUND");
         }
+        if ((flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
+            msg.append(", FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD");
+        }
         return msg.toString();
     }
 }
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index cd07793..fd89b97 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -16,13 +16,19 @@
 
 package com.android.server.display;
 
+import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
+import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
+import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
+import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
+import static android.hardware.display.DisplayManager
+        .VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
+
 import com.android.internal.util.IndentingPrintWriter;
 
 import android.Manifest;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.hardware.SensorManager;
-import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManagerGlobal;
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.display.DisplayViewport;
@@ -1446,11 +1452,17 @@
                 throw new IllegalArgumentException("Surface can't be single-buffered");
             }
 
-            if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
-                flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
+            if ((flags & VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
+                flags |= VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
+
+                // Public displays can't be allowed to show content when locked.
+                if ((flags & VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
+                    throw new IllegalArgumentException(
+                            "Public display must not be marked as SHOW_WHEN_LOCKED_INSECURE");
+                }
             }
-            if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) {
-                flags &= ~DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
+            if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) {
+                flags &= ~VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
             }
 
             if (projection != null) {
@@ -1465,7 +1477,7 @@
             }
 
             if (callingUid != Process.SYSTEM_UID &&
-                    (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
+                    (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
                 if (!canProjectVideo(projection)) {
                     throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
                             + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate "
@@ -1473,7 +1485,7 @@
                             + "display.");
                 }
             }
-            if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
+            if ((flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
                 if (!canProjectSecureVideo(projection)) {
                     throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT "
                             + "or an appropriate MediaProjection token to create a "
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 287a25a..40a8952 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -223,6 +223,9 @@
             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_ROUND) != 0) {
                 mBaseDisplayInfo.flags |= Display.FLAG_ROUND;
             }
+            if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
+                mBaseDisplayInfo.flags |= Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
+            }
             mBaseDisplayInfo.type = deviceInfo.type;
             mBaseDisplayInfo.address = deviceInfo.address;
             mBaseDisplayInfo.name = deviceInfo.name;
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 9d0fde5..74e025d 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -16,8 +16,14 @@
 
 package com.android.server.display;
 
+import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
+import static android.hardware.display.DisplayManager
+        .VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
+import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION;
+import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
+import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
+
 import android.content.Context;
-import android.hardware.display.DisplayManager;
 import android.hardware.display.IVirtualDisplayCallback;
 import android.media.projection.IMediaProjection;
 import android.media.projection.IMediaProjectionCallback;
@@ -63,7 +69,7 @@
     public DisplayDevice createVirtualDisplayLocked(IVirtualDisplayCallback callback,
             IMediaProjection projection, int ownerUid, String ownerPackageName,
             String name, int width, int height, int densityDpi, Surface surface, int flags) {
-        boolean secure = (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0;
+        boolean secure = (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0;
         IBinder appToken = callback.asBinder();
         IBinder displayToken = SurfaceControl.createDisplay(name, secure);
         final String baseUniqueId =
@@ -308,23 +314,23 @@
                 mInfo.yDpi = mDensityDpi;
                 mInfo.presentationDeadlineNanos = 1000000000L / (int) REFRESH_RATE; // 1 frame
                 mInfo.flags = 0;
-                if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) == 0) {
+                if ((mFlags & VIRTUAL_DISPLAY_FLAG_PUBLIC) == 0) {
                     mInfo.flags |= DisplayDeviceInfo.FLAG_PRIVATE
                             | DisplayDeviceInfo.FLAG_NEVER_BLANK;
                 }
-                if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
+                if ((mFlags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
                     mInfo.flags &= ~DisplayDeviceInfo.FLAG_NEVER_BLANK;
                 } else {
                     mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY;
                 }
 
-                if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
+                if ((mFlags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
                     mInfo.flags |= DisplayDeviceInfo.FLAG_SECURE;
                 }
-                if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION) != 0) {
+                if ((mFlags & VIRTUAL_DISPLAY_FLAG_PRESENTATION) != 0) {
                     mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION;
 
-                    if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
+                    if ((mFlags & VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
                         // For demonstration purposes, allow rotation of the external display.
                         // In the future we might allow the user to configure this directly.
                         if ("portrait".equals(SystemProperties.get(
@@ -333,6 +339,9 @@
                         }
                     }
                 }
+                if ((mFlags & VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
+                    mInfo.flags |= DisplayDeviceInfo.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
+                }
                 mInfo.type = Display.TYPE_VIRTUAL;
                 mInfo.touch = DisplayDeviceInfo.TOUCH_NONE;
                 mInfo.state = mSurface != null ? Display.STATE_ON : Display.STATE_OFF;
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 1feae3d..e2e0d6b 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -41,6 +41,7 @@
 import android.os.IRemoteCallback;
 import android.os.PowerManager;
 import android.os.PowerManager.WakeLock;
+import android.security.KeyStore;
 import android.os.RemoteException;
 import android.os.SELinux;
 import android.os.SystemClock;
@@ -63,7 +64,6 @@
 
 import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
 import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprintClientCallback;
-
 import android.hardware.fingerprint.Fingerprint;
 import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.IFingerprintService;
@@ -276,8 +276,18 @@
         }
     }
 
-    protected void handleAuthenticated(long deviceId, int fingerId, int groupId) {
+    protected void handleAuthenticated(long deviceId, int fingerId, int groupId,
+            ArrayList<Byte> token) {
         ClientMonitor client = mCurrentClient;
+        if (fingerId != 0) {
+            // Ugh...
+            final byte[] byteToken = new byte[token.size()];
+            for (int i = 0; i < token.size(); i++) {
+                byteToken[i] = token.get(i);
+            }
+            // Send to Keystore
+            KeyStore.getInstance().addAuthToken(byteToken);
+        }
         if (client != null && client.onAuthenticated(fingerId, groupId)) {
             removeClient(client);
         }
@@ -721,11 +731,12 @@
         }
 
         @Override
-        public void onAuthenticated(final long deviceId, final int fingerId, final int groupId) {
+        public void onAuthenticated(final long deviceId, final int fingerId, final int groupId,
+                ArrayList<Byte> token) {
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    handleAuthenticated(deviceId, fingerId, groupId);
+                    handleAuthenticated(deviceId, fingerId, groupId, token);
                 }
             });
         }
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index fbb39384..3793b91 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -84,6 +84,7 @@
 import android.util.Xml;
 import android.view.IInputFilter;
 import android.view.IInputFilterHost;
+import android.view.IWindow;
 import android.view.InputChannel;
 import android.view.InputDevice;
 import android.view.InputEvent;
@@ -180,6 +181,9 @@
     IInputFilter mInputFilter; // guarded by mInputFilterLock
     InputFilterHost mInputFilterHost; // guarded by mInputFilterLock
 
+    private IWindow mFocusedWindow;
+    private boolean mFocusedWindowHasCapture;
+
     private static native long nativeInit(InputManagerService service,
             Context context, MessageQueue messageQueue);
     private static native void nativeStart(long ptr);
@@ -226,6 +230,7 @@
     private static native void nativeSetPointerIconType(long ptr, int iconId);
     private static native void nativeReloadPointerIcons(long ptr);
     private static native void nativeSetCustomPointerIcon(long ptr, PointerIcon icon);
+    private static native void nativeSetPointerCapture(long ptr, boolean detached);
 
     // Input event injection constants defined in InputDispatcher.h.
     private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
@@ -1503,7 +1508,16 @@
         }
     }
 
-    public void setInputWindows(InputWindowHandle[] windowHandles) {
+    public void setInputWindows(InputWindowHandle[] windowHandles,
+            InputWindowHandle focusedWindowHandle) {
+        final IWindow newFocusedWindow =
+            focusedWindowHandle != null ? focusedWindowHandle.clientWindow : null;
+        if (mFocusedWindow != newFocusedWindow) {
+            mFocusedWindow = newFocusedWindow;
+            if (mFocusedWindowHasCapture) {
+                setPointerCapture(false);
+            }
+        }
         nativeSetInputWindows(mPtr, windowHandles);
     }
 
@@ -1511,6 +1525,30 @@
         nativeSetFocusedApplication(mPtr, application);
     }
 
+    @Override
+    public void requestPointerCapture(IBinder windowToken, boolean enabled) {
+        if (mFocusedWindow == null || mFocusedWindow.asBinder() != windowToken) {
+            Slog.e(TAG, "requestPointerCapture called for a window that has no focus: "
+                    + windowToken);
+            return;
+        }
+        if (mFocusedWindowHasCapture == enabled) {
+            Slog.i(TAG, "requestPointerCapture: already " + (enabled ? "enabled" : "disabled"));
+            return;
+        }
+        setPointerCapture(enabled);
+        try {
+            mFocusedWindow.dispatchPointerCaptureChanged(enabled);
+        } catch (RemoteException ex) {
+            /* ignore */
+        }
+    }
+
+    private void setPointerCapture(boolean enabled) {
+        mFocusedWindowHasCapture = enabled;
+        nativeSetPointerCapture(mPtr, enabled);
+    }
+
     public void setInputDispatchMode(boolean enabled, boolean frozen) {
         nativeSetInputDispatchMode(mPtr, enabled, frozen);
     }
diff --git a/services/core/java/com/android/server/input/InputWindowHandle.java b/services/core/java/com/android/server/input/InputWindowHandle.java
index eb3581a..3d6f7ad 100644
--- a/services/core/java/com/android/server/input/InputWindowHandle.java
+++ b/services/core/java/com/android/server/input/InputWindowHandle.java
@@ -18,6 +18,7 @@
 
 import android.graphics.Region;
 import android.view.InputChannel;
+import android.view.IWindow;
 
 /**
  * Functions as a handle for a window that can receive input.
@@ -36,6 +37,9 @@
     // The window manager's window state.
     public final Object windowState;
 
+    // The client window.
+    public final IWindow clientWindow;
+
     // The input channel associated with the window.
     public InputChannel inputChannel;
 
@@ -93,9 +97,10 @@
     private native void nativeDispose();
 
     public InputWindowHandle(InputApplicationHandle inputApplicationHandle,
-            Object windowState, int displayId) {
+            Object windowState, IWindow clientWindow, int displayId) {
         this.inputApplicationHandle = inputApplicationHandle;
         this.windowState = windowState;
+        this.clientWindow = clientWindow;
         this.displayId = displayId;
     }
 
diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java
index 1e0035d..6f49df4 100644
--- a/services/core/java/com/android/server/notification/NotificationComparator.java
+++ b/services/core/java/com/android/server/notification/NotificationComparator.java
@@ -30,7 +30,6 @@
 import android.telecom.TelecomManager;
 import android.text.TextUtils;
 import android.util.ArrayMap;
-import android.util.Slog;
 
 import java.util.Comparator;
 import java.util.Objects;
@@ -57,7 +56,15 @@
 
     @Override
     public int compare(NotificationRecord left, NotificationRecord right) {
-        // First up: sufficiently important ongoing notifications of certain categories
+        // first all colorized notifications
+        boolean leftImportantColorized = isImportantColorized(left);
+        boolean rightImportantColorized = isImportantColorized(right);
+
+        if (leftImportantColorized != rightImportantColorized) {
+            return -1 * Boolean.compare(leftImportantColorized, rightImportantColorized);
+        }
+
+        // sufficiently important ongoing notifications of certain categories
         boolean leftImportantOngoing = isImportantOngoing(left);
         boolean rightImportantOngoing = isImportantOngoing(right);
 
@@ -106,6 +113,13 @@
         return -1 * Long.compare(left.getRankingTimeMs(), right.getRankingTimeMs());
     }
 
+    private boolean isImportantColorized(NotificationRecord record) {
+        if (record.getImportance() < NotificationManager.IMPORTANCE_LOW) {
+            return false;
+        }
+        return record.getNotification().isColorized();
+    }
+
     private boolean isImportantOngoing(NotificationRecord record) {
         if (!isOngoing(record)) {
             return false;
@@ -148,7 +162,6 @@
         return (record.getNotification().flags & ongoingFlags) != 0;
     }
 
-
     private Class<? extends Notification.Style> getNotificationStyle(NotificationRecord record) {
         String templateClass =
                 record.getNotification().extras.getString(Notification.EXTRA_TEMPLATE);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 45bdb9c..60df2c4 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -55,6 +55,7 @@
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
 import android.app.AutomaticZenRule;
+import android.app.NotificationChannelGroup;
 import android.app.backup.BackupManager;
 import android.app.IActivityManager;
 import android.app.INotificationManager;
@@ -85,6 +86,7 @@
 import android.media.AudioManager;
 import android.media.AudioManagerInternal;
 import android.media.IRingtonePlayer;
+import android.metrics.LogMaker;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -131,6 +133,8 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.Preconditions;
@@ -548,6 +552,9 @@
                     return;
                 }
                 final long now = System.currentTimeMillis();
+                MetricsLogger.action(r.getLogMaker(now)
+                        .setCategory(MetricsEvent.NOTIFICATION_ITEM)
+                        .setType(MetricsEvent.TYPE_ACTION));
                 EventLogTags.writeNotificationClicked(key,
                         r.getLifespanMs(now), r.getFreshnessMs(now), r.getExposureMs(now));
 
@@ -569,6 +576,10 @@
                     return;
                 }
                 final long now = System.currentTimeMillis();
+                MetricsLogger.action(r.getLogMaker(now)
+                        .setCategory(MetricsEvent.NOTIFICATION_ITEM_ACTION)
+                        .setType(MetricsEvent.TYPE_ACTION)
+                        .setSubtype(actionIndex));
                 EventLogTags.writeNotificationActionClicked(key, actionIndex,
                         r.getLifespanMs(now), r.getFreshnessMs(now), r.getExposureMs(now));
                 // TODO: Log action click via UsageStats.
@@ -585,6 +596,8 @@
 
         @Override
         public void onPanelRevealed(boolean clearEffects, int items) {
+            MetricsLogger.visible(getContext(), MetricsEvent.NOTIFICATION_PANEL);
+            MetricsLogger.histogram(getContext(), "notification_load", items);
             EventLogTags.writeNotificationPanelRevealed(items);
             if (clearEffects) {
                 clearEffects();
@@ -593,6 +606,7 @@
 
         @Override
         public void onPanelHidden() {
+            MetricsLogger.hidden(getContext(), MetricsEvent.NOTIFICATION_PANEL);
             EventLogTags.writeNotificationPanelHidden();
         }
 
@@ -654,6 +668,9 @@
                 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));
                     EventLogTags.writeNotificationExpansion(key,
                             userAction ? 1 : 0, expanded ? 1 : 0,
                             r.getLifespanMs(now), r.getFreshnessMs(now), r.getExposureMs(now));
@@ -1601,6 +1618,21 @@
         }
 
         @Override
+        public void createNotificationChannelGroups(String pkg,
+                ParceledListSlice channelGroupList) throws RemoteException {
+            checkCallerIsSystemOrSameApp(pkg);
+            List<NotificationChannelGroup> groups = channelGroupList.getList();
+            final int groupSize = groups.size();
+            for (int i = 0; i < groupSize; i++) {
+                final NotificationChannelGroup group = groups.get(i);
+                Preconditions.checkNotNull(group, "group in list is null");
+                mRankingHelper.createNotificationChannelGroup(pkg, Binder.getCallingUid(), group,
+                        true /* fromTargetApp */);
+            }
+            savePolicyFile();
+        }
+
+        @Override
         public void createNotificationChannels(String pkg,
                 ParceledListSlice channelsList) throws RemoteException {
             checkCallerIsSystemOrSameApp(pkg);
@@ -1658,6 +1690,13 @@
         }
 
         @Override
+        public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroupsForPackage(
+                String pkg, int uid, boolean includeDeleted) {
+            checkCallerIsSystem();
+            return mRankingHelper.getNotificationChannelGroups(pkg, uid, includeDeleted);
+        }
+
+        @Override
         public ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg) {
             checkCallerIsSystemOrSameApp(pkg);
             return mRankingHelper.getNotificationChannels(
@@ -3403,6 +3442,10 @@
                     & NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_OFF) != 0)) {
                 if (DBG) Slog.v(TAG, "Suppressed SystemUI from triggering screen on");
             } else {
+                MetricsLogger.action(record.getLogMaker()
+                        .setCategory(MetricsEvent.NOTIFICATION_ALERT)
+                        .setType(MetricsEvent.TYPE_OPEN)
+                        .setSubtype((buzz ? 1 : 0) | (beep ? 2 : 0) | (blink ? 4 : 0)));
                 EventLogTags.writeNotificationAlert(key,
                         buzz ? 1 : 0, beep ? 1 : 0, blink ? 1 : 0);
                 mHandler.post(mBuzzBeepBlinked);
@@ -3873,6 +3916,10 @@
         mArchive.record(r.sbn);
 
         final long now = System.currentTimeMillis();
+        MetricsLogger.action(r.getLogMaker(now)
+                .setCategory(MetricsEvent.NOTIFICATION_ITEM)
+                .setType(MetricsEvent.TYPE_DISMISS)
+                .setSubtype(reason));
         EventLogTags.writeNotificationCanceled(canceledKey, reason,
                 r.getLifespanMs(now), r.getFreshnessMs(now), r.getExposureMs(now));
     }
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 8998128..ed2da68 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -31,6 +31,7 @@
 import android.graphics.drawable.Icon;
 import android.media.AudioAttributes;
 import android.media.AudioSystem;
+import android.metrics.LogMaker;
 import android.net.Uri;
 import android.os.Build;
 import android.os.UserHandle;
@@ -44,6 +45,8 @@
 import android.util.TimeUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.server.EventLogTags;
 
 import java.io.PrintWriter;
@@ -118,6 +121,7 @@
     private ArrayList<String> mPeopleOverride;
     private ArrayList<SnoozeCriterion> mSnoozeCriteria;
     private boolean mShowBadge;
+    private LogMaker mLogMaker;
 
     @VisibleForTesting
     public NotificationRecord(Context context, StatusBarNotification sbn,
@@ -201,18 +205,26 @@
 
     private AudioAttributes calculateAttributes() {
         final Notification n = sbn.getNotification();
-        AudioAttributes attributes = Notification.AUDIO_ATTRIBUTES_DEFAULT;
+        AudioAttributes attributes = getChannel().getAudioAttributes();
+        if (attributes == null) {
+            attributes = Notification.AUDIO_ATTRIBUTES_DEFAULT;
+        }
 
-        if (n.audioAttributes != null) {
-            // prefer audio attributes to stream type
-            attributes = n.audioAttributes;
-        } else if (n.audioStreamType >= 0 && n.audioStreamType < AudioSystem.getNumStreamTypes()) {
-            // the stream type is valid, use it
-            attributes = new AudioAttributes.Builder()
-                    .setInternalLegacyStreamType(n.audioStreamType)
-                    .build();
-        } else if (n.audioStreamType != AudioSystem.STREAM_DEFAULT) {
-            Log.w(TAG, String.format("Invalid stream type: %d", n.audioStreamType));
+        if (mPreChannelsNotification
+                && (getChannel().getUserLockedFields()
+                & NotificationChannel.USER_LOCKED_SOUND) == 0) {
+            if (n.audioAttributes != null) {
+                // prefer audio attributes to stream type
+                attributes = n.audioAttributes;
+            } else if (n.audioStreamType >= 0
+                    && n.audioStreamType < AudioSystem.getNumStreamTypes()) {
+                // the stream type is valid, use it
+                attributes = new AudioAttributes.Builder()
+                        .setInternalLegacyStreamType(n.audioStreamType)
+                        .build();
+            } else if (n.audioStreamType != AudioSystem.STREAM_DEFAULT) {
+                Log.w(TAG, String.format("Invalid stream type: %d", n.audioStreamType));
+            }
         }
         return attributes;
     }
@@ -585,9 +597,16 @@
         final long now = System.currentTimeMillis();
         mVisibleSinceMs = visible ? now : mVisibleSinceMs;
         stats.onVisibilityChanged(visible);
+        MetricsLogger.action(getLogMaker(now)
+                .setCategory(MetricsEvent.NOTIFICATION_ITEM)
+                .setType(visible ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE)
+                .addTaggedData(MetricsEvent.NOTIFICATION_SHADE_INDEX, rank));
+        if (visible) {
+            MetricsLogger.histogram(mContext, "note_freshness", getFreshnessMs(now));
+        }
         EventLogTags.writeNotificationVisibility(getKey(), visible ? 1 : 0,
-                (int) (now - mCreationTimeMs),
-                (int) (now - mUpdateTimeMs),
+                getLifespanMs(now),
+                getFreshnessMs(now),
                 0, // exposure time
                 rank);
     }
@@ -690,4 +709,25 @@
     protected void setSnoozeCriteria(ArrayList<SnoozeCriterion> snoozeCriteria) {
         mSnoozeCriteria = snoozeCriteria;
     }
+
+    public LogMaker getLogMaker(long now) {
+        if (mLogMaker == null) {
+            mLogMaker = new LogMaker(MetricsEvent.VIEW_UNKNOWN)
+                    .setPackageName(sbn.getPackageName())
+                    .addTaggedData(MetricsEvent.NOTIFICATION_ID, sbn.getId())
+                    .addTaggedData(MetricsEvent.NOTIFICATION_TAG, sbn.getTag());
+        }
+        return mLogMaker
+                .setCategory(MetricsEvent.VIEW_UNKNOWN)
+                .setType(MetricsEvent.TYPE_UNKNOWN)
+                .setSubtype(0)
+                .clearTaggedData(MetricsEvent.NOTIFICATION_SHADE_INDEX)
+                .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_CREATE_MILLIS, getLifespanMs(now))
+                .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_UPDATE_MILLIS, getFreshnessMs(now))
+                .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS, getExposureMs(now));
+    }
+
+    public LogMaker getLogMaker() {
+        return getLogMaker(System.currentTimeMillis());
+    }
 }
diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java
index 492d5c6..6a00722 100644
--- a/services/core/java/com/android/server/notification/RankingConfig.java
+++ b/services/core/java/com/android/server/notification/RankingConfig.java
@@ -16,8 +16,11 @@
 package com.android.server.notification;
 
 import android.app.NotificationChannel;
+import android.app.NotificationChannelGroup;
 import android.content.pm.ParceledListSlice;
 
+import java.util.Collection;
+
 public interface RankingConfig {
 
     void setImportance(String packageName, int uid, int importance);
@@ -25,6 +28,12 @@
     void setShowBadge(String packageName, int uid, boolean showBadge);
     boolean canShowBadge(String packageName, int uid);
 
+    Collection<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
+            int uid);
+    void createNotificationChannelGroup(String pkg, int uid, NotificationChannelGroup group,
+            boolean fromTargetApp);
+    ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
+            int uid, boolean includeDeleted);
     void createNotificationChannel(String pkg, int uid, NotificationChannel channel,
             boolean fromTargetApp);
     void updateNotificationChannel(String pkg, int uid, NotificationChannel channel);
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 1861bcb..8176e5d 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -23,6 +23,7 @@
 
 import android.app.Notification;
 import android.app.NotificationChannel;
+import android.app.NotificationChannelGroup;
 import android.app.NotificationManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -46,6 +47,7 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -59,6 +61,7 @@
     private static final String TAG_RANKING = "ranking";
     private static final String TAG_PACKAGE = "package";
     private static final String TAG_CHANNEL = "channel";
+    private static final String TAG_GROUP = "channelGroup";
 
     private static final String ATT_VERSION = "version";
     private static final String ATT_NAME = "name";
@@ -174,7 +177,6 @@
                                 safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY),
                                 safeBool(parser, ATT_SHOW_BADGE, DEFAULT_SHOW_BADGE));
 
-                        // Channels
                         final int innerDepth = parser.getDepth();
                         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                                 && (type != XmlPullParser.END_TAG
@@ -184,6 +186,17 @@
                             }
 
                             String tagName = parser.getName();
+                            // Channel groups
+                            if (TAG_GROUP.equals(tagName)) {
+                                String id = parser.getAttributeValue(null, ATT_ID);
+                                CharSequence groupName = parser.getAttributeValue(null, ATT_NAME);
+                                if (!TextUtils.isEmpty(id)) {
+                                    final NotificationChannelGroup group =
+                                            new NotificationChannelGroup(id, groupName);
+                                    r.groups.put(id, group);
+                                }
+                            }
+                            // Channels
                             if (TAG_CHANNEL.equals(tagName)) {
                                 String id = parser.getAttributeValue(null, ATT_ID);
                                 CharSequence channelName = parser.getAttributeValue(null, ATT_NAME);
@@ -302,7 +315,8 @@
             }
             final boolean hasNonDefaultSettings = r.importance != DEFAULT_IMPORTANCE
                     || r.priority != DEFAULT_PRIORITY || r.visibility != DEFAULT_VISIBILITY
-                    || r.showBadge != DEFAULT_SHOW_BADGE || r.channels.size() > 0;
+                    || r.showBadge != DEFAULT_SHOW_BADGE || r.channels.size() > 0
+                    || r.groups.size() > 0;
             if (hasNonDefaultSettings) {
                 out.startTag(null, TAG_PACKAGE);
                 out.attribute(null, ATT_NAME, r.pkg);
@@ -321,6 +335,10 @@
                     out.attribute(null, ATT_UID, Integer.toString(r.uid));
                 }
 
+                for (NotificationChannelGroup group : r.groups.values()) {
+                    group.writeXml(out);
+                }
+
                 for (NotificationChannel channel : r.channels.values()) {
                     channel.writeXml(out);
                 }
@@ -441,6 +459,21 @@
     }
 
     @Override
+    public void createNotificationChannelGroup(String pkg, int uid, NotificationChannelGroup group,
+            boolean fromTargetApp) {
+        Preconditions.checkNotNull(pkg);
+        Preconditions.checkNotNull(group);
+        Preconditions.checkNotNull(group.getId());
+        Preconditions.checkNotNull(group.getName());
+        Record r = getOrCreateRecord(pkg, uid);
+        if (r == null) {
+            throw new IllegalArgumentException("Invalid package");
+        }
+        r.groups.put(group.getId(), group);
+        updateConfig();
+    }
+
+    @Override
     public void createNotificationChannel(String pkg, int uid, NotificationChannel channel,
             boolean fromTargetApp) {
         Preconditions.checkNotNull(pkg);
@@ -454,6 +487,10 @@
         if (IMPORTANCE_NONE == r.importance) {
             throw new IllegalArgumentException("Package blocked");
         }
+        if (channel.getGroup() != null && !r.groups.containsKey(channel.getGroup())) {
+            throw new IllegalArgumentException("NotificationChannelGroup doesn't exist");
+        }
+
         NotificationChannel existing = r.channels.get(channel.getId());
         // Keep existing settings
         if (existing != null) {
@@ -532,7 +569,7 @@
             channel.setBypassDnd(updatedChannel.canBypassDnd());
         }
         if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_SOUND) == 0) {
-            channel.setSound(updatedChannel.getSound());
+            channel.setSound(updatedChannel.getSound(), updatedChannel.getAudioAttributes());
         }
         if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_VIBRATION) == 0) {
             channel.enableVibration(updatedChannel.shouldVibrate());
@@ -549,8 +586,9 @@
             channel.setShowBadge(updatedChannel.canShowBadge());
         }
         if (updatedChannel.isDeleted()) {
-            updatedChannel.setDeleted(true);
+            channel.setDeleted(true);
         }
+        // Assistant cannot change the group
 
         r.channels.put(channel.getId(), channel);
         updateConfig();
@@ -632,6 +670,51 @@
     }
 
     @Override
+    public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
+            int uid, boolean includeDeleted) {
+        Preconditions.checkNotNull(pkg);
+        List<NotificationChannelGroup> groups = new ArrayList<>();
+        Record r = getRecord(pkg, uid);
+        if (r == null) {
+            return ParceledListSlice.emptyList();
+        }
+        NotificationChannelGroup nonGrouped = new NotificationChannelGroup(null, null);
+        int N = r.channels.size();
+        for (int i = 0; i < N; i++) {
+            final NotificationChannel nc = r.channels.valueAt(i);
+            if (includeDeleted || !nc.isDeleted()) {
+                if (nc.getGroup() != null) {
+                    // lazily populate channel list
+                    NotificationChannelGroup ncg = r.groups.get(nc.getGroup());
+                    ncg.addChannel(nc);
+                } else {
+                    nonGrouped.addChannel(nc);
+                }
+            }
+        }
+        for (NotificationChannelGroup group : r.groups.values()) {
+            if (group.getChannels().size() > 0) {
+                groups.add(group);
+            }
+        }
+        if (nonGrouped.getChannels().size() > 0) {
+            groups.add(nonGrouped);
+        }
+        return new ParceledListSlice<>(groups);
+    }
+
+    @Override
+    @VisibleForTesting
+    public Collection<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
+            int uid) {
+        Record r = getRecord(pkg, uid);
+        if (r == null) {
+            return new ArrayList<>();
+        }
+        return r.groups.values();
+    }
+
+    @Override
     public ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid,
             boolean includeDeleted) {
         Preconditions.checkNotNull(pkg);
@@ -723,6 +806,12 @@
                     pw.print("  ");
                     pw.println(channel);
                 }
+                for (NotificationChannelGroup group : r.groups.values()) {
+                    pw.print(prefix);
+                    pw.print("  ");
+                    pw.print("  ");
+                    pw.println(group);
+                }
             }
         }
     }
@@ -758,6 +847,9 @@
                     for (NotificationChannel channel : r.channels.values()) {
                         record.put("channel", channel.toJson());
                     }
+                    for (NotificationChannelGroup group : r.groups.values()) {
+                        record.put("group", group.toJson());
+                    }
                 } catch (JSONException e) {
                    // pass
                 }
@@ -871,5 +963,6 @@
         boolean showBadge = DEFAULT_SHOW_BADGE;
 
         ArrayMap<String, NotificationChannel> channels = new ArrayMap<>();
+        ArrayMap<String, NotificationChannelGroup> groups = new ArrayMap<>();
    }
 }
diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
index 5dd651f..a30e0639 100644
--- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
+++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
@@ -46,7 +46,6 @@
 import java.util.concurrent.TimeUnit;
 
 import android.os.SystemClock;
-import com.android.internal.logging.MetricsLogger;
 
 /**
  * This {@link NotificationSignalExtractor} attempts to validate
@@ -264,9 +263,6 @@
         // record the best available data, so far:
         affinityOut[0] = affinity;
 
-        MetricsLogger.histogram(mBaseContext, "validate_people_cache_latency",
-                (int) (SystemClock.elapsedRealtime() - start));
-
         if (pendingLookups.isEmpty()) {
             if (VERBOSE) Slog.i(TAG, "final affinity: " + affinity);
             return null;
@@ -485,9 +481,6 @@
                 mUsageStats.registerPeopleAffinity(mRecord, mContactAffinity > NONE,
                         mContactAffinity == STARRED_CONTACT, false /* cached */);
             }
-
-            MetricsLogger.histogram(mBaseContext, "validate_people_lookup_latency",
-                    (int) (SystemClock.elapsedRealtime() - start));
         }
 
         @Override
diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java
new file mode 100644
index 0000000..04d91f8
--- /dev/null
+++ b/services/core/java/com/android/server/om/IdmapManager.java
@@ -0,0 +1,117 @@
+/*
+ * 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.server.om;
+
+import static com.android.server.om.OverlayManagerService.DEBUG;
+import static com.android.server.om.OverlayManagerService.TAG;
+
+import android.annotation.NonNull;
+import android.content.om.OverlayInfo;
+import android.content.pm.PackageInfo;
+import android.os.UserHandle;
+import android.util.Slog;
+
+import com.android.server.pm.Installer.InstallerException;
+import com.android.server.pm.Installer;
+
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+/**
+ * Handle the creation and deletion of idmap files.
+ *
+ * The actual work is performed by the idmap binary, launched through Installer
+ * and installd.
+ *
+ * Note: this class is subclassed in the OMS unit tests, and hence not marked as final.
+ */
+class IdmapManager {
+    private final Installer mInstaller;
+
+    IdmapManager(final Installer installer) {
+        mInstaller = installer;
+    }
+
+    boolean createIdmap(@NonNull final PackageInfo targetPackage,
+            @NonNull final PackageInfo overlayPackage, int userId) {
+        // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
+        if (DEBUG) {
+            Slog.d(TAG, "create idmap for " + targetPackage.packageName + " and "
+                    + overlayPackage.packageName);
+        }
+        final int sharedGid = UserHandle.getSharedAppGid(targetPackage.applicationInfo.uid);
+        final String targetPath = targetPackage.applicationInfo.getBaseCodePath();
+        final String overlayPath = overlayPackage.applicationInfo.getBaseCodePath();
+        try {
+            mInstaller.idmap(targetPath, overlayPath, sharedGid);
+        } catch (InstallerException e) {
+            Slog.w(TAG, "failed to generate idmap for " + targetPath + " and "
+                    + overlayPath + ": " + e.getMessage());
+            return false;
+        }
+        return true;
+    }
+
+    boolean removeIdmap(@NonNull final OverlayInfo oi, final int userId) {
+        // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
+        if (DEBUG) {
+            Slog.d(TAG, "remove idmap for " + oi.baseCodePath);
+        }
+        try {
+            mInstaller.removeIdmap(oi.baseCodePath);
+        } catch (InstallerException e) {
+            Slog.w(TAG, "failed to remove idmap for " + oi.baseCodePath + ": " + e.getMessage());
+            return false;
+        }
+        return true;
+    }
+
+    boolean idmapExists(@NonNull final OverlayInfo oi) {
+        // unused OverlayInfo.userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
+        return new File(getIdmapPath(oi.baseCodePath)).isFile();
+    }
+
+    boolean idmapExists(@NonNull final PackageInfo overlayPackage, final int userId) {
+        // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
+        return new File(getIdmapPath(overlayPackage.applicationInfo.getBaseCodePath())).isFile();
+    }
+
+    boolean isDangerous(@NonNull final PackageInfo overlayPackage, final int userId) {
+        // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
+        return isDangerous(getIdmapPath(overlayPackage.applicationInfo.getBaseCodePath()));
+    }
+
+    private String getIdmapPath(@NonNull final String baseCodePath) {
+        final StringBuilder sb = new StringBuilder("/data/resource-cache/");
+        sb.append(baseCodePath.substring(1).replace('/', '@'));
+        sb.append("@idmap");
+        return sb.toString();
+    }
+
+    private boolean isDangerous(@NonNull final String idmapPath) {
+        try (DataInputStream dis = new DataInputStream(new FileInputStream(idmapPath))) {
+            final int magic = dis.readInt();
+            final int version = dis.readInt();
+            final int dangerous = dis.readInt();
+            return dangerous != 0;
+        } catch (IOException e) {
+            return true;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
new file mode 100644
index 0000000..cc709ce
--- /dev/null
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -0,0 +1,850 @@
+/*
+ * 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.server.om;
+
+import static android.app.AppGlobals.getPackageManager;
+import static android.content.Intent.ACTION_PACKAGE_ADDED;
+import static android.content.Intent.ACTION_PACKAGE_CHANGED;
+import static android.content.Intent.ACTION_PACKAGE_REMOVED;
+import static android.content.Intent.ACTION_USER_REMOVED;
+import static android.content.pm.PackageManager.SIGNATURE_MATCH;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.om.IOverlayManager;
+import android.content.om.OverlayInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManagerInternal;
+import android.content.pm.UserInfo;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Environment;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.AtomicFile;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import com.android.server.FgThread;
+import com.android.server.IoThread;
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
+import com.android.server.pm.Installer;
+import com.android.server.pm.UserManagerService;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Service to manage asset overlays.
+ *
+ * <p>Asset overlays are additional resources that come from apks loaded
+ * alongside the system and app apks. This service, the OverlayManagerService
+ * (OMS), tracks which installed overlays to use and provides methods to change
+ * this. Changes propagate to running applications as part of the Activity
+ * lifecycle. This allows Activities to reread their resources at a well
+ * defined point.</p>
+ *
+ * <p>By itself, the OMS will not change what overlays should be active.
+ * Instead, it is only responsible for making sure that overlays *can* be used
+ * from a technical and security point of view and to activate overlays in
+ * response to external requests. The responsibility to toggle overlays on and
+ * off lies within components that implement different use-cases such as themes
+ * or dynamic customization.</p>
+ *
+ * <p>The OMS receives input from three sources:</p>
+ *
+ * <ul>
+ *     <li>Callbacks from the SystemService class, specifically when the
+ *     Android framework is booting and when the end user switches Android
+ *     users.</li>
+ *
+ *     <li>Intents from the PackageManagerService (PMS). Overlays are regular
+ *     apks, and whenever a package is installed (or removed, or has a
+ *     component enabled or disabled), the PMS broadcasts this as an intent.
+ *     When the OMS receives one of these intents, it updates its internal
+ *     representation of the available overlays and, if there was a visible
+ *     change, triggers an asset refresh in the affected apps.</li>
+ *
+ *     <li>External requests via the {@link IOverlayManager AIDL interface}.
+ *     The interface allows clients to read information about the currently
+ *     available overlays, change whether an overlay should be used or not, and
+ *     change the relative order in which overlay packages are loaded.
+ *     Read-access is granted if the request targets the same Android user as
+ *     the caller runs as, or if the caller holds the
+ *     INTERACT_ACROSS_USERS_FULL permission. Write-access is granted if the
+ *     caller is granted read-access and additionaly holds the
+ *     CHANGE_OVERLAY_PACKAGES permission.</li>
+ * </ul>
+ *
+ * <p>The AIDL interface works with String package names, int user IDs, and
+ * {@link OverlayInfo} objects. OverlayInfo instances are used to track a
+ * specific pair of target and overlay packages and include information such as
+ * the current state of the overlay. OverlayInfo objects are immutable.</p>
+ *
+ * <p>Internally, OverlayInfo objects are maintained by the
+ * OverlayManagerSettings class. The OMS and its helper classes are notified of
+ * changes to the settings by the OverlayManagerSettings.ChangeListener
+ * callback interface. The file /data/system/overlays.xml is used to persist
+ * the settings.</p>
+ *
+ * <p>Creation and deletion of idmap files are handled by the IdmapManager
+ * class.</p>
+ *
+ * <p>The following is an overview of OMS and its related classes. Note how box
+ * (2) does the heavy lifting, box (1) interacts with the Android framework,
+ * and box (3) replaces box (1) during unit testing.</p>
+ *
+ * <pre>
+ *         Android framework
+ *            |         ^
+ *      . . . | . . . . | . . . .
+ *     .      |         |       .
+ *     .    AIDL,   broadcasts  .
+ *     .   intents      |       .
+ *     .      |         |       . . . . . . . . . . . .
+ *     .      v         |       .                     .
+ *     .  OverlayManagerService . OverlayManagerTests .
+ *     .                  \     .     /               .
+ *     . (1)               \    .    /            (3) .
+ *      . . . . . . . . . . \ . . . / . . . . . . . . .
+ *     .                     \     /              .
+ *     . (2)                  \   /               .
+ *     .           OverlayManagerServiceImpl      .
+ *     .                  |            |          .
+ *     .                  |            |          .
+ *     . OverlayManagerSettings     IdmapManager  .
+ *     .                                          .
+ *     . . . .  . . . . . . . . . . . . . . . . . .
+ * </pre>
+ *
+ * <p>Finally, here is a list of keywords used in the OMS context.</p>
+ *
+ * <ul>
+ *     <li><b>target [package]</b> -- A regular apk that may have its resource
+ *     pool extended  by zero or more overlay packages.</li>
+ *
+ *     <li><b>overlay [package]</b> -- An apk that provides additional
+ *     resources to another apk.</li>
+ *
+ *     <li><b>OMS</b> -- The OverlayManagerService, i.e. this class.</li>
+ *
+ *     <li><b>approved</b> -- An overlay is approved if the OMS has verified
+ *     that it can be used technically speaking (its target package is
+ *     installed, at least one resource name in both packages match, the
+ *     idmap was created, etc) and that it is secure to do so. External
+ *     clients can not change this state.</li>
+ *
+ *     <li><b>not approved</b> -- The opposite of approved.</li>
+ *
+ *     <li><b>enabled</b> -- An overlay currently in active use and thus part
+ *     of resource lookups. This requires the overlay to be approved. Only
+ *     external clients can change this state.</li>
+ *
+ *     <li><b>disabled</b> -- The opposite of enabled.</li>
+ *
+ *     <li><b>idmap</b> -- A mapping of resource IDs between target and overlay
+ *     used during resource lookup. Also the name of the binary that creates
+ *     the mapping.</li>
+ * </ul>
+ */
+public final class OverlayManagerService extends SystemService {
+
+    static final String TAG = "OverlayManager";
+
+    static final boolean DEBUG = false;
+
+    static final String PERMISSION_DENIED = "Operation not permitted for user shell";
+
+    private final Object mLock = new Object();
+
+    private final AtomicFile mSettingsFile;
+
+    private final PackageManagerHelper mPackageManager;
+
+    private final UserManagerService mUserManager;
+
+    private final OverlayManagerSettings mSettings;
+
+    private final OverlayManagerServiceImpl mImpl;
+
+    private final AtomicBoolean mPersistSettingsScheduled = new AtomicBoolean(false);
+
+    public OverlayManagerService(@NonNull final Context context,
+            @NonNull final Installer installer) {
+        super(context);
+        mSettingsFile =
+            new AtomicFile(new File(Environment.getDataSystemDirectory(), "overlays.xml"));
+        mPackageManager = new PackageManagerHelper();
+        mUserManager = UserManagerService.getInstance();
+        IdmapManager im = new IdmapManager(installer);
+        mSettings = new OverlayManagerSettings();
+        mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings);
+
+        final IntentFilter packageFilter = new IntentFilter();
+        packageFilter.addAction(ACTION_PACKAGE_ADDED);
+        packageFilter.addAction(ACTION_PACKAGE_CHANGED);
+        packageFilter.addAction(ACTION_PACKAGE_REMOVED);
+        packageFilter.addDataScheme("package");
+        getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL,
+                packageFilter, null, null);
+
+        final IntentFilter userFilter = new IntentFilter();
+        userFilter.addAction(ACTION_USER_REMOVED);
+        getContext().registerReceiverAsUser(new UserReceiver(), UserHandle.ALL,
+                userFilter, null, null);
+
+        restoreSettings();
+        onSwitchUser(UserHandle.USER_SYSTEM);
+        schedulePersistSettings();
+
+        mSettings.addChangeListener(new OverlayChangeListener());
+
+        publishBinderService(Context.OVERLAY_SERVICE, mService);
+        publishLocalService(OverlayManagerService.class, this);
+    }
+
+    @Override
+    public void onStart() {
+        // Intentionally left empty.
+    }
+
+    @Override
+    public void onSwitchUser(final int newUserId) {
+        // ensure overlays in the settings are up-to-date, and propagate
+        // any asset changes to the rest of the system
+        final List<String> targets;
+        synchronized (mLock) {
+            targets = mImpl.onSwitchUser(newUserId);
+        }
+        updateAssets(newUserId, targets);
+    }
+
+    private final class PackageReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
+            final Uri data = intent.getData();
+            if (data == null) {
+                Slog.e(TAG, "Cannot handle package broadcast with null data");
+                return;
+            }
+            final String packageName = data.getSchemeSpecificPart();
+
+            final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
+
+            final int[] userIds;
+            final int extraUid = intent.getIntExtra(Intent.EXTRA_UID, UserHandle.USER_NULL);
+            if (extraUid == UserHandle.USER_NULL) {
+                userIds = mUserManager.getUserIds();
+            } else {
+                userIds = new int[] { UserHandle.getUserId(extraUid) };
+            }
+
+            switch (intent.getAction()) {
+                case ACTION_PACKAGE_ADDED:
+                    if (replacing) {
+                        onPackageUpgraded(packageName, userIds);
+                    } else {
+                        onPackageAdded(packageName, userIds);
+                    }
+                    break;
+                case ACTION_PACKAGE_CHANGED:
+                    onPackageChanged(packageName, userIds);
+                    break;
+                case ACTION_PACKAGE_REMOVED:
+                    if (replacing) {
+                        onPackageUpgrading(packageName, userIds);
+                    } else {
+                        onPackageRemoved(packageName, userIds);
+                    }
+                    break;
+                default:
+                    // do nothing
+                    break;
+            }
+        }
+
+        private void onPackageAdded(@NonNull final String packageName,
+                @NonNull final int[] userIds) {
+            for (final int userId : userIds) {
+                synchronized (mLock) {
+                    final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId, false);
+                    if (pi != null) {
+                        mPackageManager.cachePackageInfo(packageName, userId, pi);
+                        if (!isOverlayPackage(pi)) {
+                            mImpl.onTargetPackageAdded(packageName, userId);
+                        } else {
+                            mImpl.onOverlayPackageAdded(packageName, userId);
+                        }
+                    }
+                }
+            }
+        }
+
+        private void onPackageChanged(@NonNull final String packageName,
+                @NonNull final int[] userIds) {
+            for (int userId : userIds) {
+                synchronized (mLock) {
+                    final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId, false);
+                    if (pi != null) {
+                        mPackageManager.cachePackageInfo(packageName, userId, pi);
+                        if (!isOverlayPackage(pi)) {
+                            mImpl.onTargetPackageChanged(packageName, userId);
+                        } else {
+                            mImpl.onOverlayPackageChanged(packageName, userId);
+                        }
+                    }
+                }
+            }
+        }
+
+        private void onPackageUpgrading(@NonNull final String packageName,
+                @NonNull final int[] userIds) {
+            for (int userId : userIds) {
+                synchronized (mLock) {
+                    mPackageManager.forgetPackageInfo(packageName, userId);
+                    final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
+                    if (oi == null) {
+                        mImpl.onTargetPackageUpgrading(packageName, userId);
+                    } else {
+                        mImpl.onOverlayPackageUpgrading(packageName, userId);
+                    }
+                }
+            }
+        }
+
+        private void onPackageUpgraded(@NonNull final String packageName,
+                @NonNull final int[] userIds) {
+            for (int userId : userIds) {
+                synchronized (mLock) {
+                    final PackageInfo pi = mPackageManager.getPackageInfo(packageName, userId, false);
+                    if (pi != null) {
+                        mPackageManager.cachePackageInfo(packageName, userId, pi);
+                        if (!isOverlayPackage(pi)) {
+                            mImpl.onTargetPackageUpgraded(packageName, userId);
+                        } else {
+                            mImpl.onOverlayPackageUpgraded(packageName, userId);
+                        }
+                    }
+                }
+            }
+        }
+
+        private void onPackageRemoved(@NonNull final String packageName,
+                @NonNull final int[] userIds) {
+            for (int userId : userIds) {
+                synchronized (mLock) {
+                    mPackageManager.forgetPackageInfo(packageName, userId);
+                    final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
+                    if (oi == null) {
+                        mImpl.onTargetPackageRemoved(packageName, userId);
+                    } else {
+                        mImpl.onOverlayPackageRemoved(packageName, userId);
+                    }
+                }
+            }
+        }
+    }
+
+    private final class UserReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
+            switch (intent.getAction()) {
+                case ACTION_USER_REMOVED:
+                    final int userId =
+                            intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
+                    if (userId != UserHandle.USER_NULL) {
+                        synchronized (mLock) {
+                            mImpl.onUserRemoved(userId);
+                            mPackageManager.forgetAllPackageInfos(userId);
+                        }
+                    }
+                    break;
+                default:
+                    // do nothing
+                    break;
+            }
+        }
+    }
+
+    private final IBinder mService = new IOverlayManager.Stub() {
+        @Override
+        public Map<String, List<OverlayInfo>> getAllOverlays(int userId)
+                throws RemoteException {
+            userId = handleIncomingUser(userId, "getAllOverlays");
+
+            synchronized (mLock) {
+                return mImpl.getOverlaysForUser(userId);
+            }
+        }
+
+        @Override
+        public List<OverlayInfo> getOverlayInfosForTarget(@Nullable final String targetPackageName,
+                int userId) throws RemoteException {
+            userId = handleIncomingUser(userId, "getOverlayInfosForTarget");
+            if (targetPackageName == null) {
+                return Collections.emptyList();
+            }
+
+            synchronized (mLock) {
+                return mImpl.getOverlayInfosForTarget(targetPackageName, userId);
+            }
+        }
+
+        @Override
+        public OverlayInfo getOverlayInfo(@Nullable final String packageName,
+                int userId) throws RemoteException {
+            userId = handleIncomingUser(userId, "getOverlayInfo");
+            if (packageName == null) {
+                return null;
+            }
+
+            synchronized (mLock) {
+                return mImpl.getOverlayInfo(packageName, userId);
+            }
+        }
+
+        @Override
+        public boolean setEnabled(@Nullable final String packageName, final boolean enable,
+                int userId) throws RemoteException {
+            enforceChangeOverlayPackagesPermission("setEnabled");
+            userId = handleIncomingUser(userId, "setEnabled");
+            if (packageName == null) {
+                return false;
+            }
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    return mImpl.setEnabled(packageName, enable, userId);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override
+        public boolean setPriority(@Nullable final String packageName,
+                @Nullable final String parentPackageName, int userId) throws RemoteException {
+            enforceChangeOverlayPackagesPermission("setPriority");
+            userId = handleIncomingUser(userId, "setPriority");
+            if (packageName == null || parentPackageName == null) {
+                return false;
+            }
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    return mImpl.setPriority(packageName, parentPackageName, userId);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override
+        public boolean setHighestPriority(@Nullable final String packageName, int userId)
+                throws RemoteException {
+            enforceChangeOverlayPackagesPermission("setHighestPriority");
+            userId = handleIncomingUser(userId, "setHighestPriority");
+            if (packageName == null) {
+                return false;
+            }
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    return mImpl.setHighestPriority(packageName, userId);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override
+        public boolean setLowestPriority(@Nullable final String packageName, int userId)
+                throws RemoteException {
+            enforceChangeOverlayPackagesPermission("setLowestPriority");
+            userId = handleIncomingUser(userId, "setLowestPriority");
+            if (packageName == null) {
+                return false;
+            }
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    return mImpl.setLowestPriority(packageName, userId);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override
+        public void onShellCommand(@NonNull final FileDescriptor in,
+                @NonNull final FileDescriptor out, @NonNull final FileDescriptor err,
+                @NonNull final String[] args, @NonNull final ShellCallback callback,
+                @NonNull final ResultReceiver resultReceiver) {
+            (new OverlayManagerShellCommand(this)).exec(
+                    this, in, out, err, args, callback, resultReceiver);
+        }
+
+        @Override
+        protected void dump(@NonNull final FileDescriptor fd, @NonNull final PrintWriter pw,
+                @NonNull final String[] argv) {
+            enforceDumpPermission("dump");
+
+            final boolean verbose = argv.length > 0 && "--verbose".equals(argv[0]);
+
+            synchronized (mLock) {
+                mImpl.onDump(pw);
+                mPackageManager.dump(pw, verbose);
+            }
+        }
+
+        /**
+         * Ensure that the caller has permission to interact with the given userId.
+         * If the calling user is not the same as the provided user, the caller needs
+         * to hold the INTERACT_ACROSS_USERS_FULL permission (or be system uid or
+         * root).
+         *
+         * @param userId the user to interact with
+         * @param message message for any SecurityException
+         */
+        private int handleIncomingUser(final int userId, @NonNull final String message) {
+            return ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+                    Binder.getCallingUid(), userId, false, true, message, null);
+        }
+
+        /**
+         * Enforce that the caller holds the CHANGE_OVERLAY_PACKAGES permission (or is
+         * system or root).
+         *
+         * @param message used as message if SecurityException is thrown
+         * @throws SecurityException if the permission check fails
+         */
+        private void enforceChangeOverlayPackagesPermission(@NonNull final String message) {
+            getContext().enforceCallingOrSelfPermission(
+                    android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, message);
+        }
+
+        /**
+         * Enforce that the caller holds the DUMP permission (or is system or root).
+         *
+         * @param message used as message if SecurityException is thrown
+         * @throws SecurityException if the permission check fails
+         */
+        private void enforceDumpPermission(@NonNull final String message) {
+            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,
+                    message);
+        }
+    };
+
+    private boolean isOverlayPackage(@NonNull final PackageInfo pi) {
+        return pi != null && pi.overlayTarget != null;
+    }
+
+    private final class OverlayChangeListener implements OverlayManagerSettings.ChangeListener {
+        @Override
+        public void onSettingsChanged() {
+            schedulePersistSettings();
+        }
+
+        @Override
+        public void onOverlayAdded(@NonNull final OverlayInfo oi) {
+            scheduleBroadcast(Intent.ACTION_OVERLAY_ADDED, oi, oi.isEnabled());
+        }
+
+        @Override
+        public void onOverlayRemoved(@NonNull final OverlayInfo oi) {
+            scheduleBroadcast(Intent.ACTION_OVERLAY_REMOVED, oi, oi.isEnabled());
+        }
+
+        @Override
+        public void onOverlayChanged(@NonNull final OverlayInfo oi,
+                @NonNull final OverlayInfo oldOi) {
+            scheduleBroadcast(Intent.ACTION_OVERLAY_CHANGED, oi, oi.isEnabled() != oldOi.isEnabled());
+        }
+
+        @Override
+        public void onOverlayPriorityChanged(@NonNull final OverlayInfo oi) {
+            scheduleBroadcast(Intent.ACTION_OVERLAY_PRIORITY_CHANGED, oi, oi.isEnabled());
+        }
+
+        private void scheduleBroadcast(@NonNull final String action, @NonNull final OverlayInfo oi,
+                final boolean doUpdate) {
+            FgThread.getHandler().post(new BroadcastRunnable(action, oi, doUpdate));
+        }
+
+        private final class BroadcastRunnable implements Runnable {
+            private final String mAction;
+            private final OverlayInfo mOverlayInfo;
+            private final boolean mDoUpdate;
+
+            BroadcastRunnable(@NonNull final String action, @NonNull final OverlayInfo oi,
+                    final boolean doUpdate) {
+                mAction = action;
+                mOverlayInfo = oi;
+                mDoUpdate = doUpdate;
+            }
+
+            @Override
+            public void run() {
+                if (mDoUpdate) {
+                    updateAssets(mOverlayInfo.userId, mOverlayInfo.targetPackageName);
+                }
+                sendBroadcast(mAction, mOverlayInfo.targetPackageName, mOverlayInfo.packageName,
+                        mOverlayInfo.userId);
+            }
+
+            private void sendBroadcast(@NonNull final String action,
+                    @NonNull final String targetPackageName, @NonNull final String packageName,
+                    final int userId) {
+                final Intent intent = new Intent(action, Uri.fromParts("package",
+                            String.format("%s/%s", targetPackageName, packageName), null));
+                intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+                if (DEBUG) {
+                    Slog.d(TAG, String.format("send broadcast %s", intent));
+                }
+                try {
+                    ActivityManagerNative.getDefault().broadcastIntent(null, intent, null, null, 0,
+                            null, null, null, android.app.AppOpsManager.OP_NONE, null, false, false,
+                            userId);
+                } catch (RemoteException e) {
+                    // Intentionally left empty.
+                }
+            }
+
+        }
+    }
+
+    private void updateAssets(final int userId, final String targetPackageName) {
+        final List<String> list = new ArrayList<>();
+        list.add(targetPackageName);
+        updateAssets(userId, list);
+    }
+
+    private void updateAssets(final int userId, List<String> targetPackageNames) {
+        // TODO: implement when we integrate OMS properly
+    }
+
+    private void schedulePersistSettings() {
+        if (mPersistSettingsScheduled.getAndSet(true)) {
+            return;
+        }
+        IoThread.getHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                mPersistSettingsScheduled.set(false);
+                synchronized (mLock) {
+                    FileOutputStream stream = null;
+                    try {
+                        stream = mSettingsFile.startWrite();
+                        mSettings.persist(stream);
+                        mSettingsFile.finishWrite(stream);
+                    } catch (IOException | XmlPullParserException e) {
+                        mSettingsFile.failWrite(stream);
+                        Slog.e(TAG, "failed to persist overlay state", e);
+                    }
+                }
+            }
+        });
+    }
+
+    private void restoreSettings() {
+        synchronized (mLock) {
+            if (!mSettingsFile.getBaseFile().exists()) {
+                return;
+            }
+            try (final FileInputStream stream = mSettingsFile.openRead()) {
+                mSettings.restore(stream);
+
+                // We might have data for dying users if the device was
+                // restarted before we received USER_REMOVED. Remove data for
+                // users that will not exist after the system is ready.
+
+                final List<UserInfo> deadUsers = getDeadUsers();
+                final int N = deadUsers.size();
+                for (int i = 0; i < N; i++) {
+                    final UserInfo deadUser = deadUsers.get(i);
+                    final int userId = deadUser.getUserHandle().getIdentifier();
+                    mSettings.removeUser(userId);
+                }
+            } catch (IOException | XmlPullParserException e) {
+                Slog.e(TAG, "failed to restore overlay state", e);
+            }
+        }
+    }
+
+    private List<UserInfo> getDeadUsers() {
+        final List<UserInfo> users = mUserManager.getUsers(false);
+        final List<UserInfo> onlyLiveUsers = mUserManager.getUsers(true);
+        users.removeAll(onlyLiveUsers);
+        return users;
+    }
+
+    private static final class PackageManagerHelper implements
+            OverlayManagerServiceImpl.PackageManagerHelper {
+
+        private final IPackageManager mPackageManager;
+        private final PackageManagerInternal mPackageManagerInternal;
+
+        // Use a cache for performance and for consistency within OMS: because
+        // additional PACKAGE_* intents may be delivered while we process an
+        // intent, querying the PackageManagerService for the actual current
+        // state may lead to contradictions within OMS. Better then to lag
+        // behind until all pending intents have been processed.
+        private final SparseArray<HashMap<String, PackageInfo>> mCache = new SparseArray<>();
+
+        PackageManagerHelper() {
+            mPackageManager = getPackageManager();
+            mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
+        }
+
+        public PackageInfo getPackageInfo(@NonNull final String packageName, final int userId,
+                final boolean useCache) {
+            if (useCache) {
+                final PackageInfo cachedPi = getCachedPackageInfo(packageName, userId);
+                if (cachedPi != null) {
+                    return cachedPi;
+                }
+            }
+            try {
+                final PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0, userId);
+                if (useCache && pi != null) {
+                    cachePackageInfo(packageName, userId, pi);
+                }
+                return pi;
+            } catch (RemoteException e) {
+                // Intentionally left empty.
+            }
+            return null;
+        }
+
+        @Override
+        public PackageInfo getPackageInfo(@NonNull final String packageName, final int userId) {
+            return getPackageInfo(packageName, userId, true);
+        }
+
+        @Override
+        public boolean signaturesMatching(@NonNull final String packageName1,
+                @NonNull final String packageName2, final int userId) {
+            // The package manager does not support different versions of packages
+            // to be installed for different users: ignore userId for now.
+            try {
+                return mPackageManager.checkSignatures(packageName1, packageName2) == SIGNATURE_MATCH;
+            } catch (RemoteException e) {
+                // Intentionally left blank
+            }
+            return false;
+        }
+
+        @Override
+        public List<PackageInfo> getOverlayPackages(final int userId) {
+            return mPackageManagerInternal.getOverlayPackages(userId);
+        }
+
+        public PackageInfo getCachedPackageInfo(@NonNull final String packageName,
+                final int userId) {
+            final HashMap<String, PackageInfo> map = mCache.get(userId);
+            return map == null ? null : map.get(packageName);
+        }
+
+        public void cachePackageInfo(@NonNull final String packageName, final int userId,
+                @NonNull final PackageInfo pi) {
+            HashMap<String, PackageInfo> map = mCache.get(userId);
+            if (map == null) {
+                map = new HashMap<>();
+                mCache.put(userId, map);
+            }
+            map.put(packageName, pi);
+        }
+
+        public void forgetPackageInfo(@NonNull final String packageName, final int userId) {
+            final HashMap<String, PackageInfo> map = mCache.get(userId);
+            if (map == null) {
+                return;
+            }
+            map.remove(packageName);
+            if (map.isEmpty()) {
+                mCache.delete(userId);
+            }
+        }
+
+        public void forgetAllPackageInfos(final int userId) {
+            mCache.delete(userId);
+        }
+
+        private static final String TAB1 = "    ";
+        private static final String TAB2 = TAB1 + TAB1;
+
+        public void dump(@NonNull final PrintWriter pw, final boolean verbose) {
+            pw.println("PackageInfo cache");
+
+            if (!verbose) {
+                int count = 0;
+                final int N = mCache.size();
+                for (int i = 0; i < N; i++) {
+                    final int userId = mCache.keyAt(i);
+                    count += mCache.get(userId).size();
+                }
+                pw.println(TAB1 + count + " package(s)");
+                return;
+            }
+
+            if (mCache.size() == 0) {
+                pw.println(TAB1 + "<empty>");
+                return;
+            }
+
+            final int N = mCache.size();
+            for (int i = 0; i < N; i++) {
+                final int userId = mCache.keyAt(i);
+                pw.println(TAB1 + "User " + userId);
+                final HashMap<String, PackageInfo> map = mCache.get(userId);
+                for (Map.Entry<String, PackageInfo> entry : map.entrySet()) {
+                    pw.println(TAB2 + entry.getKey() + ": " + entry.getValue());
+                }
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
new file mode 100644
index 0000000..0e33409
--- /dev/null
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -0,0 +1,405 @@
+/*
+ * 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.server.om;
+
+import static android.content.om.OverlayInfo.STATE_DISABLED;
+import static android.content.om.OverlayInfo.STATE_ENABLED;
+import static android.content.om.OverlayInfo.STATE_MISSING_TARGET;
+import static android.content.om.OverlayInfo.STATE_NO_IDMAP;
+
+import static com.android.server.om.OverlayManagerService.DEBUG;
+import static com.android.server.om.OverlayManagerService.TAG;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.om.OverlayInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Slog;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Internal implementation of OverlayManagerService.
+ *
+ * Methods in this class should only be called by the OverlayManagerService.
+ * This class is not thread-safe; the caller is expected to ensure the
+ * necessary thread synchronization.
+ *
+ * @see OverlayManagerService
+ */
+final class OverlayManagerServiceImpl {
+    private final PackageManagerHelper mPackageManager;
+    private final IdmapManager mIdmapManager;
+    private final OverlayManagerSettings mSettings;
+
+    OverlayManagerServiceImpl(@NonNull final PackageManagerHelper packageManager,
+            @NonNull final IdmapManager idmapManager,
+            @NonNull final OverlayManagerSettings settings) {
+        mPackageManager = packageManager;
+        mIdmapManager = idmapManager;
+        mSettings = settings;
+    }
+
+    /*
+     * Call this when switching to a new Android user. Will return a list of
+     * target packages that must refresh their overlays. This list is the union
+     * of two sets: the set of targets with currently active overlays, and the
+     * set of targets that had, but no longer have, active overlays.
+     */
+    List<String> onSwitchUser(final int newUserId) {
+        if (DEBUG) {
+            Slog.d(TAG, "onSwitchUser newUserId=" + newUserId);
+        }
+
+        final Set<String> packagesToUpdateAssets = new ArraySet<>();
+        final ArrayMap<String, List<OverlayInfo>> tmp = mSettings.getOverlaysForUser(newUserId);
+        final int tmpSize = tmp.size();
+        final ArrayMap<String, OverlayInfo> storedOverlayInfos = new ArrayMap<>(tmpSize);
+        for (int i = 0; i < tmpSize; i++) {
+            final List<OverlayInfo> chunk = tmp.valueAt(i);
+            final int chunkSize = chunk.size();
+            for (int j = 0; j < chunkSize; j++) {
+                final OverlayInfo oi = chunk.get(j);
+                storedOverlayInfos.put(oi.packageName, oi);
+            }
+        }
+
+        List<PackageInfo> overlayPackages = mPackageManager.getOverlayPackages(newUserId);
+        final int overlayPackagesSize = overlayPackages.size();
+        for (int i = 0; i < overlayPackagesSize; i++) {
+            final PackageInfo overlayPackage = overlayPackages.get(i);
+            final OverlayInfo oi = storedOverlayInfos.get(overlayPackage.packageName);
+            if (oi == null || !oi.targetPackageName.equals(overlayPackage.overlayTarget)) {
+                if (oi != null) {
+                    packagesToUpdateAssets.add(oi.targetPackageName);
+                }
+                mSettings.init(overlayPackage.packageName, newUserId,
+                        overlayPackage.overlayTarget,
+                        overlayPackage.applicationInfo.getBaseCodePath());
+            }
+
+            try {
+                final PackageInfo targetPackage =
+                        mPackageManager.getPackageInfo(overlayPackage.overlayTarget, newUserId);
+                updateState(targetPackage, overlayPackage, newUserId);
+            } catch (OverlayManagerSettings.BadKeyException e) {
+                Slog.e(TAG, "failed to update settings", e);
+                mSettings.remove(overlayPackage.packageName, newUserId);
+            }
+
+            packagesToUpdateAssets.add(overlayPackage.overlayTarget);
+            storedOverlayInfos.remove(overlayPackage.packageName);
+        }
+
+        // any OverlayInfo left in storedOverlayInfos is no longer
+        // installed and should be removed
+        final int storedOverlayInfosSize = storedOverlayInfos.size();
+        for (int i = 0; i < storedOverlayInfosSize; i++) {
+            final OverlayInfo oi = storedOverlayInfos.get(i);
+            mSettings.remove(oi.packageName, oi.userId);
+            removeIdmapIfPossible(oi);
+            packagesToUpdateAssets.add(oi.targetPackageName);
+        }
+
+        // remove target packages that are not installed
+        final Iterator<String> iter = packagesToUpdateAssets.iterator();
+        while (iter.hasNext()) {
+            String targetPackageName = iter.next();
+            if (mPackageManager.getPackageInfo(targetPackageName, newUserId) == null) {
+                iter.remove();
+            }
+        }
+
+        return new ArrayList<String>(packagesToUpdateAssets);
+    }
+
+    void onUserRemoved(final int userId) {
+        if (DEBUG) {
+            Slog.d(TAG, "onUserRemoved userId=" + userId);
+        }
+        mSettings.removeUser(userId);
+    }
+
+    void onTargetPackageAdded(@NonNull final String packageName, final int userId) {
+        if (DEBUG) {
+            Slog.d(TAG, "onTargetPackageAdded packageName=" + packageName + " userId=" + userId);
+        }
+
+        final PackageInfo targetPackage = mPackageManager.getPackageInfo(packageName, userId);
+        updateAllOverlaysForTarget(packageName, userId, targetPackage);
+    }
+
+    void onTargetPackageChanged(@NonNull final String packageName, final int userId) {
+        if (DEBUG) {
+            Slog.d(TAG, "onTargetPackageChanged packageName=" + packageName + " userId=" + userId);
+        }
+
+        final PackageInfo targetPackage = mPackageManager.getPackageInfo(packageName, userId);
+        updateAllOverlaysForTarget(packageName, userId, targetPackage);
+    }
+
+    void onTargetPackageUpgrading(@NonNull final String packageName, final int userId) {
+        if (DEBUG) {
+            Slog.d(TAG, "onTargetPackageUpgrading packageName=" + packageName + " userId=" + userId);
+        }
+
+        updateAllOverlaysForTarget(packageName, userId, null);
+    }
+
+    void onTargetPackageUpgraded(@NonNull final String packageName, final int userId) {
+        if (DEBUG) {
+            Slog.d(TAG, "onTargetPackageUpgraded packageName=" + packageName + " userId=" + userId);
+        }
+
+        final PackageInfo targetPackage = mPackageManager.getPackageInfo(packageName, userId);
+        updateAllOverlaysForTarget(packageName, userId, targetPackage);
+    }
+
+    void onTargetPackageRemoved(@NonNull final String packageName, final int userId) {
+        if (DEBUG) {
+            Slog.d(TAG, "onTargetPackageRemoved packageName=" + packageName + " userId=" + userId);
+        }
+
+        updateAllOverlaysForTarget(packageName, userId, null);
+    }
+
+    private void updateAllOverlaysForTarget(@NonNull final String packageName, final int userId,
+            @Nullable final PackageInfo targetPackage) {
+        final List<OverlayInfo> ois = mSettings.getOverlaysForTarget(packageName, userId);
+        final int N = ois.size();
+        for (int i = 0; i < N; i++) {
+            final OverlayInfo oi = ois.get(i);
+            final PackageInfo overlayPackage = mPackageManager.getPackageInfo(oi.packageName, userId);
+            if (overlayPackage == null) {
+                mSettings.remove(oi.packageName, oi.userId);
+                removeIdmapIfPossible(oi);
+            } else {
+                try {
+                    updateState(targetPackage, overlayPackage, userId);
+                } catch (OverlayManagerSettings.BadKeyException e) {
+                    Slog.e(TAG, "failed to update settings", e);
+                    mSettings.remove(oi.packageName, userId);
+                }
+            }
+        }
+    }
+
+    void onOverlayPackageAdded(@NonNull final String packageName, final int userId) {
+        if (DEBUG) {
+            Slog.d(TAG, "onOverlayPackageAdded packageName=" + packageName + " userId=" + userId);
+        }
+
+        final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
+        if (overlayPackage == null) {
+            Slog.w(TAG, "overlay package " + packageName + " was added, but couldn't be found");
+            onOverlayPackageRemoved(packageName, userId);
+            return;
+        }
+
+        final PackageInfo targetPackage =
+                mPackageManager.getPackageInfo(overlayPackage.overlayTarget, userId);
+
+        mSettings.init(packageName, userId, overlayPackage.overlayTarget,
+                overlayPackage.applicationInfo.getBaseCodePath());
+        try {
+            updateState(targetPackage, overlayPackage, userId);
+        } catch (OverlayManagerSettings.BadKeyException e) {
+            Slog.e(TAG, "failed to update settings", e);
+            mSettings.remove(packageName, userId);
+        }
+    }
+
+    void onOverlayPackageChanged(@NonNull final String packageName, final int userId) {
+        Slog.wtf(TAG, "onOverlayPackageChanged called, but only pre-installed overlays supported");
+    }
+
+    void onOverlayPackageUpgrading(@NonNull final String packageName, final int userId) {
+        Slog.wtf(TAG, "onOverlayPackageUpgrading called, but only pre-installed overlays supported");
+    }
+
+    void onOverlayPackageUpgraded(@NonNull final String packageName, final int userId) {
+        Slog.wtf(TAG, "onOverlayPackageUpgraded called, but only pre-installed overlays supported");
+    }
+
+    void onOverlayPackageRemoved(@NonNull final String packageName, final int userId) {
+        Slog.wtf(TAG, "onOverlayPackageRemoved called, but only pre-installed overlays supported");
+    }
+
+    OverlayInfo getOverlayInfo(@NonNull final String packageName, final int userId) {
+        try {
+            return mSettings.getOverlayInfo(packageName, userId);
+        } catch (OverlayManagerSettings.BadKeyException e) {
+            return null;
+        }
+    }
+
+    List<OverlayInfo> getOverlayInfosForTarget(@NonNull final String targetPackageName,
+            final int userId) {
+        return mSettings.getOverlaysForTarget(targetPackageName, userId);
+    }
+
+    Map<String, List<OverlayInfo>> getOverlaysForUser(final int userId) {
+        return mSettings.getOverlaysForUser(userId);
+    }
+
+    boolean setEnabled(@NonNull final String packageName, final boolean enable,
+            final int userId) {
+        if (DEBUG) {
+            Slog.d(TAG, String.format("setEnabled packageName=%s enable=%s userId=%d",
+                        packageName, enable, userId));
+        }
+
+        final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
+        if (overlayPackage == null) {
+            return false;
+        }
+
+        try {
+            final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
+            final PackageInfo targetPackage =
+                    mPackageManager.getPackageInfo(oi.targetPackageName, userId);
+            mSettings.setEnabled(packageName, userId, enable);
+            updateState(targetPackage, overlayPackage, userId);
+            return true;
+        } catch (OverlayManagerSettings.BadKeyException e) {
+            return false;
+        }
+    }
+
+    boolean setPriority(@NonNull final String packageName,
+            @NonNull final String newParentPackageName, final int userId) {
+        return mSettings.setPriority(packageName, newParentPackageName, userId);
+    }
+
+    boolean setHighestPriority(@NonNull final String packageName, final int userId) {
+        return mSettings.setHighestPriority(packageName, userId);
+    }
+
+    boolean setLowestPriority(@NonNull final String packageName, final int userId) {
+        return mSettings.setLowestPriority(packageName, userId);
+    }
+
+    void onDump(@NonNull final PrintWriter pw) {
+        mSettings.dump(pw);
+    }
+
+    List<String> getEnabledOverlayPackageNames(@NonNull final String targetPackageName,
+            final int userId) {
+        final List<OverlayInfo> overlays = mSettings.getOverlaysForTarget(targetPackageName, userId);
+        final List<String> paths = new ArrayList<>(overlays.size());
+        final int N = overlays.size();
+        for (int i = 0; i < N; i++) {
+            final OverlayInfo oi = overlays.get(i);
+            if (oi.isEnabled()) {
+                paths.add(oi.packageName);
+            }
+        }
+        return paths;
+    }
+
+    private void updateState(@Nullable final PackageInfo targetPackage,
+            @NonNull final PackageInfo overlayPackage, final int userId)
+        throws OverlayManagerSettings.BadKeyException {
+        if (targetPackage != null) {
+            mIdmapManager.createIdmap(targetPackage, overlayPackage, userId);
+        }
+
+        mSettings.setBaseCodePath(overlayPackage.packageName, userId,
+                overlayPackage.applicationInfo.getBaseCodePath());
+
+        final int currentState = mSettings.getState(overlayPackage.packageName, userId);
+        final int newState = calculateNewState(targetPackage, overlayPackage, userId);
+        if (currentState != newState) {
+            if (DEBUG) {
+                Slog.d(TAG, String.format("%s:%d: %s -> %s",
+                            overlayPackage.packageName, userId,
+                            OverlayInfo.stateToString(currentState),
+                            OverlayInfo.stateToString(newState)));
+            }
+            mSettings.setState(overlayPackage.packageName, userId, newState);
+        }
+    }
+
+    private int calculateNewState(@Nullable final PackageInfo targetPackage,
+            @NonNull final PackageInfo overlayPackage, final int userId)
+        throws OverlayManagerSettings.BadKeyException {
+        if (targetPackage == null) {
+            return STATE_MISSING_TARGET;
+        }
+
+        if (!mIdmapManager.idmapExists(overlayPackage, userId)) {
+            return STATE_NO_IDMAP;
+        }
+
+        final boolean enabled = mSettings.getEnabled(overlayPackage.packageName, userId);
+        return enabled ? STATE_ENABLED : STATE_DISABLED;
+    }
+
+    private void removeIdmapIfPossible(@NonNull final OverlayInfo oi) {
+        // For a given package, all Android users share the same idmap file.
+        // This works because Android currently does not support users to
+        // install different versions of the same package. It also means we
+        // cannot remove an idmap file if any user still needs it.
+        //
+        // When/if the Android framework allows different versions of the same
+        // package to be installed for different users, idmap file handling
+        // should be revised:
+        //
+        // - an idmap file should be unique for each {user, package} pair
+        //
+        // - the path to the idmap file should be passed to the native Asset
+        //   Manager layers, just like the path to the apk is passed today
+        //
+        // As part of that change, calls to this method should be replaced by
+        // direct calls to IdmapManager.removeIdmap, without looping over all
+        // users.
+
+        if (!mIdmapManager.idmapExists(oi)) {
+            return;
+        }
+        final List<Integer> userIds = mSettings.getUsers();
+        final int N = userIds.size();
+        for (int i = 0; i < N; i++) {
+            final int userId = userIds.get(i);
+            try {
+                final OverlayInfo tmp = mSettings.getOverlayInfo(oi.packageName, userId);
+                if (tmp != null && tmp.isEnabled()) {
+                    // someone is still using the idmap file -> we cannot remove it
+                    return;
+                }
+            } catch (OverlayManagerSettings.BadKeyException e) {
+                // intentionally left empty
+            }
+        }
+        mIdmapManager.removeIdmap(oi, oi.userId);
+    }
+
+    interface PackageManagerHelper {
+        PackageInfo getPackageInfo(@NonNull String packageName, int userId);
+        boolean signaturesMatching(@NonNull String packageName1, @NonNull String packageName2,
+                                   int userId);
+        List<PackageInfo> getOverlayPackages(int userId);
+    }
+}
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
new file mode 100644
index 0000000..44908a7
--- /dev/null
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -0,0 +1,630 @@
+/*
+ * 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.server.om;
+
+import static android.content.om.OverlayInfo.STATE_UNKNOWN;
+
+import static com.android.server.om.OverlayManagerService.DEBUG;
+import static com.android.server.om.OverlayManagerService.TAG;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.om.OverlayInfo;
+import android.util.AndroidRuntimeException;
+import android.util.ArrayMap;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+/**
+ * Data structure representing the current state of all overlay packages in the
+ * system.
+ *
+ * Modifications to the data are exposed through the ChangeListener interface.
+ *
+ * @see ChangeListener
+ * @see OverlayManagerService
+ */
+final class OverlayManagerSettings {
+    private final List<ChangeListener> mListeners = new ArrayList<>();
+
+    private final ArrayList<SettingsItem> mItems = new ArrayList<>();
+
+    void init(@NonNull final String packageName, final int userId,
+            @NonNull final String targetPackageName, @NonNull final String baseCodePath) {
+        remove(packageName, userId);
+        final SettingsItem item =
+                new SettingsItem(packageName, userId, targetPackageName, baseCodePath);
+        mItems.add(item);
+    }
+
+    void remove(@NonNull final String packageName, final int userId) {
+        final SettingsItem item = select(packageName, userId);
+        if (item == null) {
+            return;
+        }
+        final OverlayInfo oi = item.getOverlayInfo();
+        mItems.remove(item);
+        if (oi != null) {
+            notifyOverlayRemoved(oi);
+        }
+    }
+
+    boolean contains(@NonNull final String packageName, final int userId) {
+        return select(packageName, userId) != null;
+    }
+
+    OverlayInfo getOverlayInfo(@NonNull final String packageName, final int userId)
+            throws BadKeyException {
+        final SettingsItem item = select(packageName, userId);
+        if (item == null) {
+            throw new BadKeyException(packageName, userId);
+        }
+        return item.getOverlayInfo();
+    }
+
+    String getTargetPackageName(@NonNull final String packageName, final int userId)
+            throws BadKeyException {
+        final SettingsItem item = select(packageName, userId);
+        if (item == null) {
+            throw new BadKeyException(packageName, userId);
+        }
+        return item.getTargetPackageName();
+    }
+
+    void setBaseCodePath(@NonNull final String packageName, final int userId,
+            @NonNull final String path) throws BadKeyException {
+        final SettingsItem item = select(packageName, userId);
+        if (item == null) {
+            throw new BadKeyException(packageName, userId);
+        }
+        item.setBaseCodePath(path);
+        notifySettingsChanged();
+    }
+
+    boolean getEnabled(@NonNull final String packageName, final int userId) throws BadKeyException {
+        final SettingsItem item = select(packageName, userId);
+        if (item == null) {
+            throw new BadKeyException(packageName, userId);
+        }
+        return item.isEnabled();
+    }
+
+    void setEnabled(@NonNull final String packageName, final int userId, final boolean enable)
+            throws BadKeyException {
+        final SettingsItem item = select(packageName, userId);
+        if (item == null) {
+            throw new BadKeyException(packageName, userId);
+        }
+        if (enable == item.isEnabled()) {
+            return; // nothing to do
+        }
+
+        item.setEnabled(enable);
+        notifySettingsChanged();
+    }
+
+    int getState(@NonNull final String packageName, final int userId) throws BadKeyException {
+        final SettingsItem item = select(packageName, userId);
+        if (item == null) {
+            throw new BadKeyException(packageName, userId);
+        }
+        return item.getState();
+    }
+
+    void setState(@NonNull final String packageName, final int userId, final int state)
+            throws BadKeyException {
+        final SettingsItem item = select(packageName, userId);
+        if (item == null) {
+            throw new BadKeyException(packageName, userId);
+        }
+        final OverlayInfo previous = item.getOverlayInfo();
+        item.setState(state);
+        final OverlayInfo current = item.getOverlayInfo();
+        if (previous.state == STATE_UNKNOWN) {
+            notifyOverlayAdded(current);
+            notifySettingsChanged();
+        } else if (current.state != previous.state) {
+            notifyOverlayChanged(current, previous);
+            notifySettingsChanged();
+        }
+    }
+
+    List<OverlayInfo> getOverlaysForTarget(@NonNull final String targetPackageName,
+            final int userId) {
+        final List<SettingsItem> items = selectWhereTarget(targetPackageName, userId);
+        if (items.isEmpty()) {
+            return Collections.emptyList();
+        }
+        final List<OverlayInfo> out = new ArrayList<>(items.size());
+        final int N = items.size();
+        for (int i = 0; i < N; i++) {
+            final SettingsItem item = items.get(i);
+            out.add(item.getOverlayInfo());
+        }
+        return out;
+    }
+
+    ArrayMap<String, List<OverlayInfo>> getOverlaysForUser(final int userId) {
+        final List<SettingsItem> items = selectWhereUser(userId);
+        if (items.isEmpty()) {
+            return ArrayMap.EMPTY;
+        }
+        final ArrayMap<String, List<OverlayInfo>> out = new ArrayMap<>(items.size());
+        final int N = items.size();
+        for (int i = 0; i < N; i++) {
+            final SettingsItem item = items.get(i);
+            final String targetPackageName = item.getTargetPackageName();
+            if (!out.containsKey(targetPackageName)) {
+                out.put(targetPackageName, new ArrayList<OverlayInfo>());
+            }
+            final List<OverlayInfo> overlays = out.get(targetPackageName);
+            overlays.add(item.getOverlayInfo());
+        }
+        return out;
+    }
+
+    List<String> getTargetPackageNamesForUser(final int userId) {
+        final List<SettingsItem> items = selectWhereUser(userId);
+        if (items.isEmpty()) {
+            return Collections.emptyList();
+        }
+        final List<String> out = new ArrayList<>();
+        final int N = items.size();
+        for (int i = 0; i < N; i++) {
+            final SettingsItem item = items.get(i);
+            final String targetPackageName = item.getTargetPackageName();
+            if (!out.contains(targetPackageName)) {
+                out.add(targetPackageName);
+            }
+        }
+        return out;
+    }
+
+    List<Integer> getUsers() {
+        final ArrayList<Integer> users = new ArrayList<>();
+        final int N = mItems.size();
+        for (int i = 0; i < N; i++) {
+            final SettingsItem item = mItems.get(i);
+            if (!users.contains(item.userId)) {
+                users.add(item.userId);
+            }
+        }
+        return users;
+    }
+
+    void removeUser(final int userId) {
+        final Iterator<SettingsItem> iter = mItems.iterator();
+        while (iter.hasNext()) {
+            final SettingsItem item = iter.next();
+            if (item.userId == userId) {
+                iter.remove();
+            }
+        }
+    }
+
+    boolean setPriority(@NonNull final String packageName,
+            @NonNull final String newParentPackageName, final int userId) {
+        if (packageName.equals(newParentPackageName)) {
+            return false;
+        }
+        final SettingsItem rowToMove = select(packageName, userId);
+        if (rowToMove == null) {
+            return false;
+        }
+        final SettingsItem newParentRow = select(newParentPackageName, userId);
+        if (newParentRow == null) {
+            return false;
+        }
+        if (!rowToMove.getTargetPackageName().equals(newParentRow.getTargetPackageName())) {
+            return false;
+        }
+
+        mItems.remove(rowToMove);
+        final ListIterator<SettingsItem> iter = mItems.listIterator();
+        while (iter.hasNext()) {
+            final SettingsItem item = iter.next();
+            if (item.userId == userId && item.packageName.equals(newParentPackageName)) {
+                iter.add(rowToMove);
+                notifyOverlayPriorityChanged(rowToMove.getOverlayInfo());
+                notifySettingsChanged();
+                return true;
+            }
+        }
+
+        Slog.wtf(TAG, "failed to find the parent item a second time");
+        return false;
+    }
+
+    boolean setLowestPriority(@NonNull final String packageName, final int userId) {
+        final SettingsItem item = select(packageName, userId);
+        if (item == null) {
+            return false;
+        }
+        mItems.remove(item);
+        mItems.add(0, item);
+        notifyOverlayPriorityChanged(item.getOverlayInfo());
+        notifySettingsChanged();
+        return true;
+    }
+
+    boolean setHighestPriority(@NonNull final String packageName, final int userId) {
+        final SettingsItem item = select(packageName, userId);
+        if (item == null) {
+            return false;
+        }
+        mItems.remove(item);
+        mItems.add(item);
+        notifyOverlayPriorityChanged(item.getOverlayInfo());
+        notifySettingsChanged();
+        return true;
+    }
+
+    private static final String TAB1 = "    ";
+    private static final String TAB2 = TAB1 + TAB1;
+    private static final String TAB3 = TAB2 + TAB1;
+
+    void dump(@NonNull final PrintWriter pw) {
+        pw.println("Settings");
+        dumpItems(pw);
+        dumpListeners(pw);
+    }
+
+    private void dumpItems(@NonNull final PrintWriter pw) {
+        pw.println(TAB1 + "Items");
+
+        if (mItems.isEmpty()) {
+            pw.println(TAB2 + "<none>");
+            return;
+        }
+
+        final int N = mItems.size();
+        for (int i = 0; i < N; i++) {
+            final SettingsItem item = mItems.get(i);
+            final StringBuilder sb = new StringBuilder();
+            sb.append(TAB2 + item.packageName + ":" + item.userId + " {\n");
+            sb.append(TAB3 + "packageName.......: " + item.packageName + "\n");
+            sb.append(TAB3 + "userId............: " + item.userId + "\n");
+            sb.append(TAB3 + "targetPackageName.: " + item.getTargetPackageName() + "\n");
+            sb.append(TAB3 + "baseCodePath......: " + item.getBaseCodePath() + "\n");
+            sb.append(TAB3 + "state.............: " + OverlayInfo.stateToString(item.getState()) + "\n");
+            sb.append(TAB3 + "isEnabled.........: " + item.isEnabled() + "\n");
+            sb.append(TAB2 + "}");
+            pw.println(sb.toString());
+        }
+    }
+
+    private void dumpListeners(@NonNull final PrintWriter pw) {
+        pw.println(TAB1 + "Change listeners");
+
+        if (mListeners.isEmpty()) {
+            pw.println(TAB2 + "<none>");
+            return;
+        }
+
+        final int N = mListeners.size();
+        for (int i = 0; i < N; i++) {
+            final ChangeListener ch = mListeners.get(i);
+            pw.println(TAB2 + ch);
+        }
+
+    }
+
+    void restore(@NonNull final InputStream is) throws IOException, XmlPullParserException {
+        Serializer.restore(mItems, is);
+    }
+
+    void persist(@NonNull final OutputStream os) throws IOException, XmlPullParserException {
+        Serializer.persist(mItems, os);
+    }
+
+    private static final class Serializer {
+        private static final String TAG_OVERLAYS = "overlays";
+        private static final String TAG_ITEM = "item";
+
+        private static final String ATTR_BASE_CODE_PATH = "baseCodePath";
+        private static final String ATTR_IS_ENABLED = "isEnabled";
+        private static final String ATTR_PACKAGE_NAME = "packageName";
+        private static final String ATTR_STATE = "state";
+        private static final String ATTR_TARGET_PACKAGE_NAME = "targetPackageName";
+        private static final String ATTR_USER_ID = "userId";
+        private static final String ATTR_VERSION = "version";
+
+        private static final int CURRENT_VERSION = 1;
+
+        public static void restore(@NonNull final ArrayList<SettingsItem> table,
+                @NonNull final InputStream is) throws IOException, XmlPullParserException {
+
+            try (InputStreamReader reader = new InputStreamReader(is)) {
+                table.clear();
+                final XmlPullParser parser = Xml.newPullParser();
+                parser.setInput(reader);
+                XmlUtils.beginDocument(parser, TAG_OVERLAYS);
+                int version = XmlUtils.readIntAttribute(parser, ATTR_VERSION);
+                if (version != CURRENT_VERSION) {
+                    throw new XmlPullParserException("unrecognized version " + version);
+                }
+                int depth = parser.getDepth();
+
+                while (XmlUtils.nextElementWithin(parser, depth)) {
+                    switch (parser.getName()) {
+                        case TAG_ITEM:
+                            final SettingsItem item = restoreRow(parser, depth + 1);
+                            table.add(item);
+                            break;
+                    }
+                }
+            }
+        }
+
+        private static SettingsItem restoreRow(@NonNull final XmlPullParser parser, final int depth)
+                throws IOException {
+            final String packageName = XmlUtils.readStringAttribute(parser, ATTR_PACKAGE_NAME);
+            final int userId = XmlUtils.readIntAttribute(parser, ATTR_USER_ID);
+            final String targetPackageName = XmlUtils.readStringAttribute(parser,
+                    ATTR_TARGET_PACKAGE_NAME);
+            final String baseCodePath = XmlUtils.readStringAttribute(parser, ATTR_BASE_CODE_PATH);
+            final int state = XmlUtils.readIntAttribute(parser, ATTR_STATE);
+            final boolean isEnabled = XmlUtils.readBooleanAttribute(parser, ATTR_IS_ENABLED);
+
+            return new SettingsItem(packageName, userId, targetPackageName, baseCodePath, state,
+                    isEnabled);
+        }
+
+        public static void persist(@NonNull final ArrayList<SettingsItem> table,
+                @NonNull final OutputStream os) throws IOException, XmlPullParserException {
+            final FastXmlSerializer xml = new FastXmlSerializer();
+            xml.setOutput(os, "utf-8");
+            xml.startDocument(null, true);
+            xml.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+            xml.startTag(null, TAG_OVERLAYS);
+            XmlUtils.writeIntAttribute(xml, ATTR_VERSION, CURRENT_VERSION);
+
+            final int N = table.size();
+            for (int i = 0; i < N; i++) {
+                final SettingsItem item = table.get(i);
+                persistRow(xml, item);
+            }
+            xml.endTag(null, TAG_OVERLAYS);
+            xml.endDocument();
+        }
+
+        private static void persistRow(@NonNull final FastXmlSerializer xml,
+                @NonNull final SettingsItem item) throws IOException {
+            xml.startTag(null, TAG_ITEM);
+            XmlUtils.writeStringAttribute(xml, ATTR_PACKAGE_NAME, item.packageName);
+            XmlUtils.writeIntAttribute(xml, ATTR_USER_ID, item.userId);
+            XmlUtils.writeStringAttribute(xml, ATTR_TARGET_PACKAGE_NAME, item.targetPackageName);
+            XmlUtils.writeStringAttribute(xml, ATTR_BASE_CODE_PATH, item.baseCodePath);
+            XmlUtils.writeIntAttribute(xml, ATTR_STATE, item.state);
+            XmlUtils.writeBooleanAttribute(xml, ATTR_IS_ENABLED, item.isEnabled);
+            xml.endTag(null, TAG_ITEM);
+        }
+    }
+
+    private static final class SettingsItem {
+        private final int userId;
+        private final String packageName;
+        private final String targetPackageName;
+        private String baseCodePath;
+        private int state;
+        private boolean isEnabled;
+        private OverlayInfo cache;
+
+        SettingsItem(@NonNull final String packageName, final int userId,
+                @NonNull final String targetPackageName, @NonNull final String baseCodePath,
+                final int state, final boolean isEnabled) {
+            this.packageName = packageName;
+            this.userId = userId;
+            this.targetPackageName = targetPackageName;
+            this.baseCodePath = baseCodePath;
+            this.state = state;
+            this.isEnabled = isEnabled;
+            cache = null;
+        }
+
+        SettingsItem(@NonNull final String packageName, final int userId,
+                @NonNull final String targetPackageName, @NonNull final String baseCodePath) {
+            this(packageName, userId, targetPackageName, baseCodePath, STATE_UNKNOWN,
+                    false);
+        }
+
+        private String getTargetPackageName() {
+            return targetPackageName;
+        }
+
+        private String getBaseCodePath() {
+            return baseCodePath;
+        }
+
+        private void setBaseCodePath(@NonNull final String path) {
+            if (!baseCodePath.equals(path)) {
+                baseCodePath = path;
+                invalidateCache();
+            }
+        }
+
+        private int getState() {
+            return state;
+        }
+
+        private void setState(final int state) {
+            if (this.state != state) {
+                this.state = state;
+                invalidateCache();
+            }
+        }
+
+        private boolean isEnabled() {
+            return isEnabled;
+        }
+
+        private void setEnabled(final boolean enable) {
+            if (isEnabled != enable) {
+                isEnabled = enable;
+                invalidateCache();
+            }
+        }
+
+        private OverlayInfo getOverlayInfo() {
+            if (cache == null) {
+                cache = new OverlayInfo(packageName, targetPackageName, baseCodePath,
+                        state, userId);
+            }
+            return cache;
+        }
+
+        private void invalidateCache() {
+            cache = null;
+        }
+    }
+
+    private SettingsItem select(@NonNull final String packageName, final int userId) {
+        final int N = mItems.size();
+        for (int i = 0; i < N; i++) {
+            final SettingsItem item = mItems.get(i);
+            if (item.userId == userId && item.packageName.equals(packageName)) {
+                return item;
+            }
+        }
+        return null;
+    }
+
+    private List<SettingsItem> selectWhereUser(final int userId) {
+        final ArrayList<SettingsItem> items = new ArrayList<>();
+        final int N = mItems.size();
+        for (int i = 0; i < N; i++) {
+            final SettingsItem item = mItems.get(i);
+            if (item.userId == userId) {
+                items.add(item);
+            }
+        }
+        return items;
+    }
+
+    private List<SettingsItem> selectWhereTarget(@NonNull final String targetPackageName,
+            final int userId) {
+        final ArrayList<SettingsItem> items = new ArrayList<>();
+        final int N = mItems.size();
+        for (int i = 0; i < N; i++) {
+            final SettingsItem item = mItems.get(i);
+            if (item.userId == userId && item.getTargetPackageName().equals(targetPackageName)) {
+                items.add(item);
+            }
+        }
+        return items;
+    }
+
+    private void assertNotNull(@Nullable final Object o) {
+        if (o == null) {
+            throw new AndroidRuntimeException("object must not be null");
+        }
+    }
+
+    void addChangeListener(@NonNull final ChangeListener listener) {
+        mListeners.add(listener);
+    }
+
+    void removeChangeListener(@NonNull final ChangeListener listener) {
+        mListeners.remove(listener);
+    }
+
+    private void notifySettingsChanged() {
+        final int N = mListeners.size();
+        for (int i = 0; i < N; i++) {
+            final ChangeListener listener = mListeners.get(i);
+            listener.onSettingsChanged();
+        }
+    }
+
+    private void notifyOverlayAdded(@NonNull final OverlayInfo oi) {
+        if (DEBUG) {
+            assertNotNull(oi);
+        }
+        final int N = mListeners.size();
+        for (int i = 0; i < N; i++) {
+            final ChangeListener listener = mListeners.get(i);
+            listener.onOverlayAdded(oi);
+        }
+    }
+
+    private void notifyOverlayRemoved(@NonNull final OverlayInfo oi) {
+        if (DEBUG) {
+            assertNotNull(oi);
+        }
+        final int N = mListeners.size();
+        for (int i = 0; i < N; i++) {
+            final ChangeListener listener = mListeners.get(i);
+            listener.onOverlayRemoved(oi);
+        }
+    }
+
+    private void notifyOverlayChanged(@NonNull final OverlayInfo oi,
+            @NonNull final OverlayInfo oldOi) {
+        if (DEBUG) {
+            assertNotNull(oi);
+            assertNotNull(oldOi);
+        }
+        final int N = mListeners.size();
+        for (int i = 0; i < N; i++) {
+            final ChangeListener listener = mListeners.get(i);
+            listener.onOverlayChanged(oi, oldOi);
+        }
+    }
+
+    private void notifyOverlayPriorityChanged(@NonNull final OverlayInfo oi) {
+        if (DEBUG) {
+            assertNotNull(oi);
+        }
+        final int N = mListeners.size();
+        for (int i = 0; i < N; i++) {
+            final ChangeListener listener = mListeners.get(i);
+            listener.onOverlayPriorityChanged(oi);
+        }
+    }
+
+    interface ChangeListener {
+        void onSettingsChanged();
+        void onOverlayAdded(@NonNull OverlayInfo oi);
+        void onOverlayRemoved(@NonNull OverlayInfo oi);
+        void onOverlayChanged(@NonNull OverlayInfo oi, @NonNull OverlayInfo oldOi);
+        void onOverlayPriorityChanged(@NonNull OverlayInfo oi);
+    }
+
+    static final class BadKeyException extends RuntimeException {
+        BadKeyException(@NonNull final String packageName, final int userId) {
+            super("Bad key packageName=" + packageName + " userId=" + userId);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
new file mode 100644
index 0000000..29ddaf4
--- /dev/null
+++ b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
@@ -0,0 +1,187 @@
+/*
+ * 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.server.om;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.om.IOverlayManager;
+import android.content.om.OverlayInfo;
+import android.os.RemoteException;
+import android.os.ShellCommand;
+import android.os.UserHandle;
+
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Implementation of 'cmd overlay' commands.
+ *
+ * This class provides an interface to the OverlayManagerService via adb.
+ * Intended only for manual debugging. Execute 'adb exec-out cmd overlay help'
+ * for a list of available commands.
+ */
+final class OverlayManagerShellCommand extends ShellCommand {
+    private final IOverlayManager mInterface;
+
+    OverlayManagerShellCommand(@NonNull final IOverlayManager iom) {
+        mInterface = iom;
+    }
+
+    @Override
+    public int onCommand(@Nullable final String cmd) {
+        if (cmd == null) {
+            return handleDefaultCommands(cmd);
+        }
+        final PrintWriter err = getErrPrintWriter();
+        try {
+            switch (cmd) {
+                case "list":
+                    return runList();
+                case "enable":
+                    return runEnableDisable(true);
+                case "disable":
+                    return runEnableDisable(false);
+                case "set-priority":
+                    return runSetPriority();
+                default:
+                    return handleDefaultCommands(cmd);
+            }
+        } catch (IllegalArgumentException e) {
+            err.println("Error: " + e.getMessage());
+        } catch (RemoteException e) {
+            err.println("Remote exception: " + e);
+        }
+        return -1;
+    }
+
+    @Override
+    public void onHelp() {
+        final PrintWriter out = getOutPrintWriter();
+        out.println("Overlay manager (overlay) commands:");
+        out.println("  help");
+        out.println("    Print this help text.");
+        out.println("  dump [--verbose] [--user USER_ID] [PACKAGE [PACKAGE [...]]]");
+        out.println("    Print debugging information about the overlay manager.");
+        out.println("  list [--user USER_ID] [PACKAGE [PACKAGE [...]]]");
+        out.println("    Print information about target and overlay packages.");
+        out.println("    Overlay packages are printed in priority order. With optional");
+        out.println("    parameters PACKAGEs, limit output to the specified packages");
+        out.println("    but include more information about each package.");
+        out.println("  enable [--user USER_ID] PACKAGE");
+        out.println("    Enable overlay package PACKAGE.");
+        out.println("  disable [--user USER_ID] PACKAGE");
+        out.println("    Disable overlay package PACKAGE.");
+        out.println("  set-priority [--user USER_ID] PACKAGE PARENT|lowest|highest");
+        out.println("    Change the priority of the overlay PACKAGE to be just higher than");
+        out.println("    the priority of PACKAGE_PARENT If PARENT is the special keyword");
+        out.println("    'lowest', change priority of PACKAGE to the lowest priority.");
+        out.println("    If PARENT is the special keyword 'highest', change priority of");
+        out.println("    PACKAGE to the highest priority.");
+    }
+
+    private int runList() throws RemoteException {
+        final PrintWriter out = getOutPrintWriter();
+        final PrintWriter err = getErrPrintWriter();
+
+        int userId = UserHandle.USER_SYSTEM;
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "--user":
+                    userId = UserHandle.parseUserArg(getNextArgRequired());
+                    break;
+                default:
+                    err.println("Error: Unknown option: " + opt);
+                    return 1;
+            }
+        }
+
+        final Map<String, List<OverlayInfo>> allOverlays = mInterface.getAllOverlays(userId);
+        for (final String targetPackageName : allOverlays.keySet()) {
+            out.println(targetPackageName);
+            List<OverlayInfo> overlaysForTarget = allOverlays.get(targetPackageName);
+            final int N = overlaysForTarget.size();
+            for (int i = 0; i < N; i++) {
+                final OverlayInfo oi = overlaysForTarget.get(i);
+                String status;
+                switch (oi.state) {
+                    case OverlayInfo.STATE_ENABLED:
+                        status = "[x]";
+                        break;
+                    case OverlayInfo.STATE_DISABLED:
+                        status = "[ ]";
+                        break;
+                    default:
+                        status = "---";
+                        break;
+                }
+                out.println(String.format("%s %s", status, oi.packageName));
+            }
+            out.println();
+        }
+        return 0;
+    }
+
+    private int runEnableDisable(final boolean enable) throws RemoteException {
+        final PrintWriter err = getErrPrintWriter();
+
+        int userId = UserHandle.USER_SYSTEM;
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "--user":
+                    userId = UserHandle.parseUserArg(getNextArgRequired());
+                    break;
+                default:
+                    err.println("Error: Unknown option: " + opt);
+                    return 1;
+            }
+        }
+
+        final String packageName = getNextArgRequired();
+        return mInterface.setEnabled(packageName, enable, userId) ? 0 : 1;
+    }
+
+    private int runSetPriority() throws RemoteException {
+        final PrintWriter err = getErrPrintWriter();
+
+        int userId = UserHandle.USER_SYSTEM;
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "--user":
+                    userId = UserHandle.parseUserArg(getNextArgRequired());
+                    break;
+                default:
+                    err.println("Error: Unknown option: " + opt);
+                    return 1;
+            }
+        }
+
+        final String packageName = getNextArgRequired();
+        final String newParentPackageName = getNextArgRequired();
+
+        if ("highest".equals(newParentPackageName)) {
+            return mInterface.setHighestPriority(packageName, userId) ? 0 : 1;
+        } else if ("lowest".equals(newParentPackageName)) {
+            return mInterface.setLowestPriority(packageName, userId) ? 0 : 1;
+        } else {
+            return mInterface.setPriority(packageName, newParentPackageName, userId) ? 0 : 1;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/pm/KeySetManagerService.java b/services/core/java/com/android/server/pm/KeySetManagerService.java
index 0de0c92..49d3c8b 100644
--- a/services/core/java/com/android/server/pm/KeySetManagerService.java
+++ b/services/core/java/com/android/server/pm/KeySetManagerService.java
@@ -287,7 +287,7 @@
         for (int i = 0; i < defMapSize; i++) {
             String alias = definedMapping.keyAt(i);
             ArraySet<PublicKey> pubKeys = definedMapping.valueAt(i);
-            if (alias != null && pubKeys != null || pubKeys.size() > 0) {
+            if (alias != null && pubKeys != null && pubKeys.size() > 0) {
                 KeySetHandle ks = addKeySetLPw(pubKeys);
                 newKeySetAliases.put(alias, ks.getId());
             }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c6b7dde..85c1152 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -706,6 +706,8 @@
 
     boolean mFirstBoot;
 
+    PackageManagerInternal.ExternalSourcesPolicy mExternalSourcesPolicy;
+
     // System configuration read by SystemConfig.
     final int[] mGlobalGids;
     final SparseArray<ArraySet<String>> mSystemPermissions;
@@ -829,6 +831,7 @@
     private List<String> mKeepUninstalledPackages;
 
     private UserManagerInternal mUserManagerInternal;
+    private final UserDataPreparer mUserDataPreparer;
 
     private File mCacheDir;
 
@@ -1864,6 +1867,18 @@
                     res.removedInfo.args.doPostDeleteLI(true);
                 }
             }
+
+            if (!isEphemeral(res.pkg)) {
+                // Notify DexManager that the package was installed for new users.
+                // The updated users should already be indexed and the package code paths
+                // should not change.
+                // Don't notify the manager for ephemeral apps as they are not expected to
+                // survive long enough to benefit of background optimizations.
+                for (int userId : firstUsers) {
+                    PackageInfo info = getPackageInfo(packageName, /*flags*/ 0, userId);
+                    mDexManager.notifyPackageInstalled(info, userId);
+                }
+            }
         }
 
         // If someone is watching installs - notify them
@@ -2248,8 +2263,8 @@
             mEphemeralInstallDir = new File(dataDir, "app-ephemeral");
             mAsecInternalPath = new File(dataDir, "app-asec").getPath();
             mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
-
-            sUserManager = new UserManagerService(context, this, mPackages);
+            mUserDataPreparer = new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore);
+            sUserManager = new UserManagerService(context, this, mUserDataPreparer, mPackages);
 
             // Propagate permission configuration in to package manager.
             ArrayMap<String, SystemConfig.PermissionEntry> permConfig
@@ -21251,99 +21266,6 @@
     }
 
     /**
-     * Prepare storage areas for given user on all mounted devices.
-     */
-    void prepareUserData(int userId, int userSerial, int flags) {
-        synchronized (mInstallLock) {
-            final StorageManager storage = mContext.getSystemService(StorageManager.class);
-            for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
-                final String volumeUuid = vol.getFsUuid();
-                prepareUserDataLI(volumeUuid, userId, userSerial, flags, true);
-            }
-        }
-    }
-
-    private void prepareUserDataLI(String volumeUuid, int userId, int userSerial, int flags,
-            boolean allowRecover) {
-        // Prepare storage and verify that serial numbers are consistent; if
-        // there's a mismatch we need to destroy to avoid leaking data
-        final StorageManager storage = mContext.getSystemService(StorageManager.class);
-        try {
-            storage.prepareUserStorage(volumeUuid, userId, userSerial, flags);
-
-            if ((flags & StorageManager.FLAG_STORAGE_DE) != 0 && !mOnlyCore) {
-                UserManagerService.enforceSerialNumber(
-                        Environment.getDataUserDeDirectory(volumeUuid, userId), userSerial);
-                if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) {
-                    UserManagerService.enforceSerialNumber(
-                            Environment.getDataSystemDeDirectory(userId), userSerial);
-                }
-            }
-            if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && !mOnlyCore) {
-                UserManagerService.enforceSerialNumber(
-                        Environment.getDataUserCeDirectory(volumeUuid, userId), userSerial);
-                if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) {
-                    UserManagerService.enforceSerialNumber(
-                            Environment.getDataSystemCeDirectory(userId), userSerial);
-                }
-            }
-
-            synchronized (mInstallLock) {
-                mInstaller.createUserData(volumeUuid, userId, userSerial, flags);
-            }
-        } catch (Exception e) {
-            logCriticalInfo(Log.WARN, "Destroying user " + userId + " on volume " + volumeUuid
-                    + " because we failed to prepare: " + e);
-            destroyUserDataLI(volumeUuid, userId,
-                    StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
-
-            if (allowRecover) {
-                // Try one last time; if we fail again we're really in trouble
-                prepareUserDataLI(volumeUuid, userId, userSerial, flags, false);
-            }
-        }
-    }
-
-    /**
-     * Destroy storage areas for given user on all mounted devices.
-     */
-    void destroyUserData(int userId, int flags) {
-        synchronized (mInstallLock) {
-            final StorageManager storage = mContext.getSystemService(StorageManager.class);
-            for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
-                final String volumeUuid = vol.getFsUuid();
-                destroyUserDataLI(volumeUuid, userId, flags);
-            }
-        }
-    }
-
-    private void destroyUserDataLI(String volumeUuid, int userId, int flags) {
-        final StorageManager storage = mContext.getSystemService(StorageManager.class);
-        try {
-            // Clean up app data, profile data, and media data
-            mInstaller.destroyUserData(volumeUuid, userId, flags);
-
-            // Clean up system data
-            if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) {
-                if ((flags & StorageManager.FLAG_STORAGE_DE) != 0) {
-                    FileUtils.deleteContentsAndDir(Environment.getUserSystemDirectory(userId));
-                    FileUtils.deleteContentsAndDir(Environment.getDataSystemDeDirectory(userId));
-                }
-                if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) {
-                    FileUtils.deleteContentsAndDir(Environment.getDataSystemCeDirectory(userId));
-                }
-            }
-
-            // Data with special labels is now gone, so finish the job
-            storage.destroyUserStorage(volumeUuid, userId, flags);
-
-        } catch (Exception e) {
-            logCriticalInfo(Log.WARN,
-                    "Failed to destroy user " + userId + " on volume " + volumeUuid + ": " + e);
-        }
-    }
-
-    /**
      * Examine all users present on given mounted volume, and destroy data
      * belonging to users that are no longer valid, or whose user ID has been
      * recycled.
@@ -21358,6 +21280,8 @@
                 .listFilesOrEmpty(Environment.getDataSystemDeDirectory()));
         Collections.addAll(files, FileUtils
                 .listFilesOrEmpty(Environment.getDataSystemCeDirectory()));
+        Collections.addAll(files, FileUtils
+                .listFilesOrEmpty(Environment.getDataMiscCeDirectory()));
         for (File file : files) {
             if (!file.isDirectory()) continue;
 
@@ -21388,7 +21312,7 @@
 
             if (destroyUser) {
                 synchronized (mInstallLock) {
-                    destroyUserDataLI(volumeUuid, userId,
+                    mUserDataPreparer.destroyUserDataLI(volumeUuid, userId,
                             StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
                 }
             }
@@ -22848,6 +22772,49 @@
         public String getSetupWizardPackageName() {
             return mSetupWizardPackage;
         }
+
+        public void setExternalSourcesPolicy(ExternalSourcesPolicy policy) {
+            if (policy != null) {
+                mExternalSourcesPolicy = policy;
+            }
+        }
+
+        @Override
+        public List<PackageInfo> getOverlayPackages(int userId) {
+            final ArrayList<PackageInfo> overlayPackages = new ArrayList<PackageInfo>();
+            synchronized (mPackages) {
+                for (PackageParser.Package p : mPackages.values()) {
+                    if (p.mOverlayTarget != null) {
+                        PackageInfo pkg = generatePackageInfo((PackageSetting)p.mExtras, 0, userId);
+                        if (pkg != null) {
+                            overlayPackages.add(pkg);
+                        }
+                    }
+                }
+            }
+            return overlayPackages;
+        }
+
+        @Override
+        public List<String> getTargetPackageNames(int userId) {
+            List<String> targetPackages = new ArrayList<>();
+            synchronized (mPackages) {
+                for (PackageParser.Package p : mPackages.values()) {
+                    if (p.mOverlayTarget == null) {
+                        targetPackages.add(p.packageName);
+                    }
+                }
+            }
+            return targetPackages;
+        }
+
+
+        @Override
+        public boolean setEnabledOverlayPackages(int userId, String targetPackageName,
+                List<String> overlayPackageNames) {
+            // TODO: implement when we integrate OMS properly
+            return false;
+        }
     }
 
     @Override
@@ -22937,4 +22904,38 @@
         }
         return PackageManager.INSTALL_REASON_UNKNOWN;
     }
+
+    @Override
+    public boolean canRequestPackageInstalls(String packageName, int userId) {
+        int callingUid = Binder.getCallingUid();
+        int uid = getPackageUid(packageName, 0, userId);
+        if (callingUid != uid && callingUid != Process.ROOT_UID
+                && callingUid != Process.SYSTEM_UID) {
+            throw new SecurityException(
+                    "Caller uid " + callingUid + " does not own package " + packageName);
+        }
+        ApplicationInfo info = getApplicationInfo(packageName, 0, userId);
+        if (info == null) {
+            return false;
+        }
+        if (info.targetSdkVersion < Build.VERSION_CODES.O) {
+            throw new UnsupportedOperationException(
+                    "Operation only supported on apps targeting Android O or higher");
+        }
+        String appOpPermission = Manifest.permission.REQUEST_INSTALL_PACKAGES;
+        String[] packagesDeclaringPermission = getAppOpPermissionPackages(appOpPermission);
+        if (!ArrayUtils.contains(packagesDeclaringPermission, packageName)) {
+            throw new SecurityException("Need to declare " + appOpPermission + " to call this api");
+        }
+        if (sUserManager.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, userId)) {
+            return false;
+        }
+        if (mExternalSourcesPolicy != null) {
+            int isTrusted = mExternalSourcesPolicy.getPackageTrustedToInstallApps(packageName, uid);
+            if (isTrusted != PackageManagerInternal.ExternalSourcesPolicy.USER_DEFAULT) {
+                return isTrusted == PackageManagerInternal.ExternalSourcesPolicy.USER_TRUSTED;
+            }
+        }
+        return checkUidPermission(appOpPermission, uid) == PERMISSION_GRANTED;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java b/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
index 6e96726..6eac5e3 100644
--- a/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
+++ b/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
@@ -25,7 +25,6 @@
 import android.content.pm.LauncherApps;
 import android.content.pm.LauncherApps.PinItemRequest;
 import android.content.pm.ShortcutInfo;
-import android.os.Binder;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.util.Log;
@@ -168,8 +167,8 @@
         mLock = lock;
     }
 
-    public boolean isRequestPinnedShortcutSupported(int callingUserId) {
-        return getRequestPinShortcutConfirmationActivity(callingUserId) != null;
+    public boolean isRequestPinItemSupported(int callingUserId, int requestType) {
+        return getRequestPinConfirmationActivity(callingUserId, requestType) != null;
     }
 
     /**
@@ -185,8 +184,10 @@
         // First, make sure the launcher supports it.
 
         // Find the confirmation activity in the default launcher.
+        final int requestType = inShortcut != null ?
+                PinItemRequest.REQUEST_TYPE_SHORTCUT : PinItemRequest.REQUEST_TYPE_APPWIDGET;
         final Pair<ComponentName, Integer> confirmActivity =
-                getRequestPinShortcutConfirmationActivity(userId);
+                getRequestPinConfirmationActivity(userId, requestType);
 
         // If the launcher doesn't support it, just return a rejected result and finish.
         if (confirmActivity == null) {
@@ -210,7 +211,8 @@
             request = new PinItemRequest(inAppWidget,
                     new PinItemRequestInner(this, resultIntent, launcherUid));
         }
-        return startRequestConfirmActivity(confirmActivity.first, launcherUserId, request);
+        return startRequestConfirmActivity(confirmActivity.first, launcherUserId, request,
+                requestType);
     }
 
     /**
@@ -330,9 +332,13 @@
     }
 
     private boolean startRequestConfirmActivity(ComponentName activity, int launcherUserId,
-            PinItemRequest request) {
+            PinItemRequest request, int requestType) {
+        final String action = requestType == LauncherApps.PinItemRequest.REQUEST_TYPE_SHORTCUT ?
+                LauncherApps.ACTION_CONFIRM_PIN_SHORTCUT :
+                LauncherApps.ACTION_CONFIRM_PIN_APPWIDGET;
+
         // Start the activity.
-        final Intent confirmIntent = new Intent(LauncherApps.ACTION_CONFIRM_PIN_ITEM);
+        final Intent confirmIntent = new Intent(action);
         confirmIntent.setComponent(activity);
         confirmIntent.putExtra(LauncherApps.EXTRA_PIN_ITEM_REQUEST, request);
         confirmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
@@ -351,13 +357,13 @@
     }
 
     /**
-     * Find the activity that handles {@link LauncherApps#ACTION_CONFIRM_PIN_ITEM} in the
+     * Find the activity that handles {@link LauncherApps#ACTION_CONFIRM_PIN_SHORTCUT} in the
      * default launcher.
      */
     @Nullable
     @VisibleForTesting
-    Pair<ComponentName, Integer> getRequestPinShortcutConfirmationActivity(
-            int callingUserId) {
+    Pair<ComponentName, Integer> getRequestPinConfirmationActivity(
+            int callingUserId, int requestType) {
         // Find the default launcher.
         final int launcherUserId = mService.getParentOrSelfUserId(callingUserId);
         final ComponentName defaultLauncher = mService.getDefaultLauncher(launcherUserId);
@@ -367,7 +373,7 @@
             return null;
         }
         final ComponentName activity = mService.injectGetPinConfirmationActivity(
-                defaultLauncher.getPackageName(), launcherUserId);
+                defaultLauncher.getPackageName(), launcherUserId, requestType);
         return (activity == null) ? null : Pair.create(activity, launcherUserId);
     }
 
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 56d679e..c0fc24c 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -2117,10 +2117,11 @@
     }
 
     @Override
-    public boolean isRequestPinShortcutSupported(int callingUserId) {
+    public boolean isRequestPinItemSupported(int callingUserId, int requestType) {
         final long token = injectClearCallingIdentity();
         try {
-            return mShortcutRequestPinProcessor.isRequestPinnedShortcutSupported(callingUserId);
+            return mShortcutRequestPinProcessor
+                    .isRequestPinItemSupported(callingUserId, requestType);
         } finally {
             injectRestoreCallingIdentity(token);
         }
@@ -2621,6 +2622,11 @@
             Preconditions.checkNotNull(appWidget);
             return requestPinItem(callingPackage, userId, null, appWidget, resultIntent);
         }
+
+        @Override
+        public boolean isRequestPinItemSupported(int callingUserId, int requestType) {
+            return ShortcutService.this.isRequestPinItemSupported(callingUserId, requestType);
+        }
     }
 
     final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -3250,16 +3256,19 @@
     }
 
     /**
-     * Get the {@link LauncherApps#ACTION_CONFIRM_PIN_ITEM} activity in a given package.
+     * Get the {@link LauncherApps#ACTION_CONFIRM_PIN_SHORTCUT} or
+     * {@link LauncherApps#ACTION_CONFIRM_PIN_APPWIDGET} activity in a given package depending on
+     * the requestType.
      */
     @Nullable
     ComponentName injectGetPinConfirmationActivity(@NonNull String launcherPackageName,
-            int launcherUserId) {
+            int launcherUserId, int requestType) {
         Preconditions.checkNotNull(launcherPackageName);
+        String action = requestType == LauncherApps.PinItemRequest.REQUEST_TYPE_SHORTCUT ?
+                LauncherApps.ACTION_CONFIRM_PIN_SHORTCUT :
+                LauncherApps.ACTION_CONFIRM_PIN_APPWIDGET;
 
-        final Intent confirmIntent = new Intent(LauncherApps.ACTION_CONFIRM_PIN_ITEM);
-        confirmIntent.setPackage(launcherPackageName);
-
+        final Intent confirmIntent = new Intent(action).setPackage(launcherPackageName);
         final List<ResolveInfo> candidates = queryActivities(
                 confirmIntent, launcherUserId, /* exportedOnly =*/ false);
         for (ResolveInfo ri : candidates) {
diff --git a/services/core/java/com/android/server/pm/UserDataPreparer.java b/services/core/java/com/android/server/pm/UserDataPreparer.java
new file mode 100644
index 0000000..52599fd
--- /dev/null
+++ b/services/core/java/com/android/server/pm/UserDataPreparer.java
@@ -0,0 +1,139 @@
+/*
+ * 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.server.pm;
+
+import android.content.Context;
+import android.os.Environment;
+import android.os.FileUtils;
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
+import android.util.Log;
+
+import java.util.Objects;
+
+import static com.android.server.pm.PackageManagerService.logCriticalInfo;
+
+/**
+ * Helper class for preparing and destroying user storage
+ */
+class UserDataPreparer {
+    private final Object mInstallLock;
+    private final Context mContext;
+    private final boolean mOnlyCore;
+    private final Installer mInstaller;
+
+    UserDataPreparer(Installer installer, Object installLock, Context context, boolean onlyCore) {
+        mInstallLock = installLock;
+        mContext = context;
+        mOnlyCore = onlyCore;
+        mInstaller = installer;
+    }
+
+    /**
+     * Prepare storage areas for given user on all mounted devices.
+     */
+    void prepareUserData(int userId, int userSerial, int flags) {
+        synchronized (mInstallLock) {
+            final StorageManager storage = mContext.getSystemService(StorageManager.class);
+            for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
+                final String volumeUuid = vol.getFsUuid();
+                prepareUserDataLI(volumeUuid, userId, userSerial, flags, true);
+            }
+        }
+    }
+
+    private void prepareUserDataLI(String volumeUuid, int userId, int userSerial, int flags,
+            boolean allowRecover) {
+        // Prepare storage and verify that serial numbers are consistent; if
+        // there's a mismatch we need to destroy to avoid leaking data
+        final StorageManager storage = mContext.getSystemService(StorageManager.class);
+        try {
+            storage.prepareUserStorage(volumeUuid, userId, userSerial, flags);
+
+            if ((flags & StorageManager.FLAG_STORAGE_DE) != 0 && !mOnlyCore) {
+                UserManagerService.enforceSerialNumber(
+                        Environment.getDataUserDeDirectory(volumeUuid, userId), userSerial);
+                if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) {
+                    UserManagerService.enforceSerialNumber(
+                            Environment.getDataSystemDeDirectory(userId), userSerial);
+                }
+            }
+            if ((flags & StorageManager.FLAG_STORAGE_CE) != 0 && !mOnlyCore) {
+                UserManagerService.enforceSerialNumber(
+                        Environment.getDataUserCeDirectory(volumeUuid, userId), userSerial);
+                if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) {
+                    UserManagerService.enforceSerialNumber(
+                            Environment.getDataSystemCeDirectory(userId), userSerial);
+                }
+            }
+
+            mInstaller.createUserData(volumeUuid, userId, userSerial, flags);
+        } catch (Exception e) {
+            logCriticalInfo(Log.WARN, "Destroying user " + userId + " on volume " + volumeUuid
+                    + " because we failed to prepare: " + e);
+            destroyUserDataLI(volumeUuid, userId,
+                    StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
+
+            if (allowRecover) {
+                // Try one last time; if we fail again we're really in trouble
+                prepareUserDataLI(volumeUuid, userId, userSerial, flags, false);
+            }
+        }
+    }
+
+    /**
+     * Destroy storage areas for given user on all mounted devices.
+     */
+    void destroyUserData(int userId, int flags) {
+        synchronized (mInstallLock) {
+            final StorageManager storage = mContext.getSystemService(StorageManager.class);
+            for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
+                final String volumeUuid = vol.getFsUuid();
+                destroyUserDataLI(volumeUuid, userId, flags);
+            }
+        }
+    }
+
+    void destroyUserDataLI(String volumeUuid, int userId, int flags) {
+        final StorageManager storage = mContext.getSystemService(StorageManager.class);
+        try {
+            // Clean up app data, profile data, and media data
+            mInstaller.destroyUserData(volumeUuid, userId, flags);
+
+            // Clean up system data
+            if (Objects.equals(volumeUuid, StorageManager.UUID_PRIVATE_INTERNAL)) {
+                if ((flags & StorageManager.FLAG_STORAGE_DE) != 0) {
+                    FileUtils.deleteContentsAndDir(Environment.getUserSystemDirectory(userId));
+                    FileUtils.deleteContentsAndDir(Environment.getDataSystemDeDirectory(userId));
+                    FileUtils.deleteContentsAndDir(Environment.getDataMiscDeDirectory(userId));
+                }
+                if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) {
+                    FileUtils.deleteContentsAndDir(Environment.getDataSystemCeDirectory(userId));
+                    FileUtils.deleteContentsAndDir(Environment.getDataMiscCeDirectory(userId));
+                }
+            }
+
+            // Data with special labels is now gone, so finish the job
+            storage.destroyUserStorage(volumeUuid, userId, flags);
+
+        } catch (Exception e) {
+            logCriticalInfo(Log.WARN,
+                    "Failed to destroy user " + userId + " on volume " + volumeUuid + ": " + e);
+        }
+    }
+
+}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 984120f..455d3e4 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -227,6 +227,7 @@
     private final Context mContext;
     private final PackageManagerService mPm;
     private final Object mPackagesLock;
+    private final UserDataPreparer mUserDataPreparer;
     // Short-term lock for internal state, when interaction/sync with PM is not required
     private final Object mUsersLock = new Object();
     private final Object mRestrictionsLock = new Object();
@@ -433,7 +434,7 @@
     // TODO b/28848102 Add support for test dependencies injection
     @VisibleForTesting
     UserManagerService(Context context) {
-        this(context, null, new Object(), context.getCacheDir());
+        this(context, null, null, new Object(), context.getCacheDir());
     }
 
     /**
@@ -441,16 +442,18 @@
      * associated with the package manager, and the given lock is the
      * package manager's own lock.
      */
-    UserManagerService(Context context, PackageManagerService pm, Object packagesLock) {
-        this(context, pm, packagesLock, Environment.getDataDirectory());
+    UserManagerService(Context context, PackageManagerService pm, UserDataPreparer userDataPreparer,
+            Object packagesLock) {
+        this(context, pm, userDataPreparer, packagesLock, Environment.getDataDirectory());
     }
 
     private UserManagerService(Context context, PackageManagerService pm,
-            Object packagesLock, File dataDir) {
+            UserDataPreparer userDataPreparer, Object packagesLock, File dataDir) {
         mContext = context;
         mPm = pm;
         mPackagesLock = packagesLock;
         mHandler = new MainHandler();
+        mUserDataPreparer = userDataPreparer;
         synchronized (mPackagesLock) {
             mUsersDir = new File(dataDir, USER_INFO_DIR);
             mUsersDir.mkdirs();
@@ -716,7 +719,7 @@
             return null;
         }
         int parentUserId = profile.profileGroupId;
-        if (parentUserId == UserInfo.NO_PROFILE_GROUP_ID) {
+        if (parentUserId == userHandle || parentUserId == UserInfo.NO_PROFILE_GROUP_ID) {
             return null;
         } else {
             return getUserInfoLU(parentUserId);
@@ -2494,7 +2497,7 @@
             }
             final StorageManager storage = mContext.getSystemService(StorageManager.class);
             storage.createUserKey(userId, userInfo.serialNumber, userInfo.isEphemeral());
-            mPm.prepareUserData(userId, userInfo.serialNumber,
+            mUserDataPreparer.prepareUserData(userId, userInfo.serialNumber,
                     StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
             mPm.createNewUser(userId, disallowedPackages);
             userInfo.partial = false;
@@ -2788,7 +2791,7 @@
         mPm.cleanUpUser(this, userHandle);
 
         // Clean up all data before removing metadata
-        mPm.destroyUserData(userHandle,
+        mUserDataPreparer.destroyUserData(userHandle,
                 StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
 
         // Remove this user from the list
@@ -3129,7 +3132,7 @@
         final int userSerial = userInfo.serialNumber;
         // Migrate only if build fingerprints mismatch
         boolean migrateAppsData = !Build.FINGERPRINT.equals(userInfo.lastLoggedInFingerprint);
-        mPm.prepareUserData(userId, userSerial, StorageManager.FLAG_STORAGE_DE);
+        mUserDataPreparer.prepareUserData(userId, userSerial, StorageManager.FLAG_STORAGE_DE);
         mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_DE, migrateAppsData);
 
         if (userId != UserHandle.USER_SYSTEM) {
@@ -3151,7 +3154,7 @@
         final int userSerial = userInfo.serialNumber;
         // Migrate only if build fingerprints mismatch
         boolean migrateAppsData = !Build.FINGERPRINT.equals(userInfo.lastLoggedInFingerprint);
-        mPm.prepareUserData(userId, userSerial, StorageManager.FLAG_STORAGE_CE);
+        mUserDataPreparer.prepareUserData(userId, userSerial, StorageManager.FLAG_STORAGE_CE);
         mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_CE, migrateAppsData);
     }
 
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index a179aab..c5f1646 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -143,8 +143,8 @@
                 // - new installed splits
                 // If we can't find the owner of the dex we simply do not track it. The impact is
                 // that the dex file will not be considered for offline optimizations.
-                // TODO(calin): add hooks for install/uninstall notifications to
-                // capture new or obsolete packages.
+                // TODO(calin): add hooks for move/uninstall notifications to
+                // capture package moves or obsolete packages.
                 if (DEBUG) {
                     Slog.i(TAG, "Could not find owning package for dex file: " + dexPath);
                 }
@@ -168,6 +168,20 @@
         }
     }
 
+    public void notifyPackageInstalled(PackageInfo info, int userId) {
+        cachePackageCodeLocation(info, userId);
+    }
+
+    private void cachePackageCodeLocation(PackageInfo info, int userId) {
+        PackageCodeLocations pcl = mPackageCodeLocationsCache.get(info.packageName);
+        if (pcl != null) {
+            pcl.mergeAppDataDirs(info.applicationInfo, userId);
+        } else {
+            mPackageCodeLocationsCache.put(info.packageName,
+                new PackageCodeLocations(info.applicationInfo, userId));
+        }
+    }
+
     private void loadInternal(Map<Integer, List<PackageInfo>> existingPackages) {
         Map<String, Set<Integer>> packageToUsersMap = new HashMap<>();
         // Cache the code locations for the installed packages. This allows for
@@ -177,13 +191,8 @@
             int userId = entry.getKey();
             for (PackageInfo pi : packageInfoList) {
                 // Cache the code locations.
-                PackageCodeLocations pcl = mPackageCodeLocationsCache.get(pi.packageName);
-                if (pcl != null) {
-                    pcl.mergeAppDataDirs(pi.applicationInfo, userId);
-                } else {
-                    mPackageCodeLocationsCache.put(pi.packageName,
-                        new PackageCodeLocations(pi.applicationInfo, userId));
-                }
+                cachePackageCodeLocation(pi, userId);
+
                 // Cache a map from package name to the set of user ids who installed the package.
                 // We will use it to sync the data and remove obsolete entries from
                 // mPackageDexUsage.
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index e1b6c87..238866a 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -57,6 +57,7 @@
 import android.service.vr.IVrManager;
 import android.service.vr.IVrStateCallbacks;
 import android.util.EventLog;
+import android.util.KeyValueListParser;
 import android.util.Log;
 import android.util.PrintWriterPrinter;
 import android.util.Slog;
@@ -522,6 +523,65 @@
     // True if we are currently in VR Mode.
     private boolean mIsVrModeEnabled;
 
+    /**
+     * All times are in milliseconds. These constants are kept synchronized with the system
+     * global Settings. Any access to this class or its fields should be done while
+     * holding the PowerManagerService.mLock lock.
+     */
+    private final class Constants extends ContentObserver {
+        // Key names stored in the settings value.
+        private static final String KEY_NO_CACHED_WAKE_LOCKS = "no_cached_wake_locks";
+
+        private static final boolean DEFAULT_NO_CACHED_WAKE_LOCKS = true;
+
+        // Prevent processes that are cached from holding wake locks?
+        public boolean NO_CACHED_WAKE_LOCKS = DEFAULT_NO_CACHED_WAKE_LOCKS;
+
+        private ContentResolver mResolver;
+        private final KeyValueListParser mParser = new KeyValueListParser(',');
+
+        public Constants(Handler handler) {
+            super(handler);
+        }
+
+        public void start(ContentResolver resolver) {
+            mResolver = resolver;
+            mResolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.POWER_MANAGER_CONSTANTS), false, this);
+            updateConstants();
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            updateConstants();
+        }
+
+        private void updateConstants() {
+            synchronized (mLock) {
+                try {
+                    mParser.setString(Settings.Global.getString(mResolver,
+                            Settings.Global.POWER_MANAGER_CONSTANTS));
+                } catch (IllegalArgumentException e) {
+                    // Failed to parse the settings string, log this and move on
+                    // with defaults.
+                    Slog.e(TAG, "Bad alarm manager settings", e);
+                }
+
+                NO_CACHED_WAKE_LOCKS = mParser.getBoolean(KEY_NO_CACHED_WAKE_LOCKS,
+                        DEFAULT_NO_CACHED_WAKE_LOCKS);
+            }
+        }
+
+        void dump(PrintWriter pw) {
+            pw.println("  Settings " + Settings.Global.POWER_MANAGER_CONSTANTS + ":");
+
+            pw.print("    "); pw.print(KEY_NO_CACHED_WAKE_LOCKS); pw.print("=");
+            pw.println(NO_CACHED_WAKE_LOCKS);
+        }
+    }
+
+    final Constants mConstants;
+
     private native void nativeInit();
 
     private static native void nativeAcquireSuspendBlocker(String name);
@@ -538,6 +598,7 @@
                 Process.THREAD_PRIORITY_DISPLAY, false /*allowIo*/);
         mHandlerThread.start();
         mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
+        mConstants = new Constants(mHandler);
 
         synchronized (mLock) {
             mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
@@ -616,6 +677,9 @@
                     mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
                     mPolicy);
 
+            final ContentResolver resolver = mContext.getContentResolver();
+            mConstants.start(resolver);
+
             mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
                     createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),
                     mHandler);
@@ -629,7 +693,6 @@
                     mDisplayPowerCallbacks, mHandler, sensorManager);
 
             // Register for settings changes.
-            final ContentResolver resolver = mContext.getContentResolver();
             resolver.registerContentObserver(Settings.Secure.getUriFor(
                     Settings.Secure.SCREENSAVER_ENABLED),
                     false, mSettingsObserver, UserHandle.USER_ALL);
@@ -2795,7 +2858,7 @@
                             state.mProcState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
                         disabled = true;
                     }
-                } else {
+                } else if (mConstants.NO_CACHED_WAKE_LOCKS) {
                     disabled = !wakeLock.mUidState.mActive &&
                             wakeLock.mUidState.mProcState
                                     != ActivityManager.PROCESS_STATE_NONEXISTENT &&
@@ -3005,6 +3068,7 @@
         final WirelessChargerDetector wcd;
         synchronized (mLock) {
             pw.println("Power Manager State:");
+            mConstants.dump(pw);
             pw.println("  mDirty=0x" + Integer.toHexString(mDirty));
             pw.println("  mWakefulness=" + PowerManagerInternal.wakefulnessToString(mWakefulness));
             pw.println("  mWakefulnessChanging=" + mWakefulnessChanging);
diff --git a/services/core/java/com/android/server/storage/DiskStatsLoggingService.java b/services/core/java/com/android/server/storage/DiskStatsLoggingService.java
index 0a3abf3..7c43162 100644
--- a/services/core/java/com/android/server/storage/DiskStatsLoggingService.java
+++ b/services/core/java/com/android/server/storage/DiskStatsLoggingService.java
@@ -21,6 +21,7 @@
 import android.app.job.JobScheduler;
 import android.app.job.JobService;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.PackageStats;
 import android.os.AsyncTask;
@@ -28,6 +29,7 @@
 import android.os.Environment;
 import android.os.Environment.UserEnvironment;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -54,7 +56,7 @@
     public boolean onStartJob(JobParameters params) {
         // We need to check the preconditions again because they may not be enforced for
         // subsequent runs.
-        if (!isCharging(this)) {
+        if (!isCharging(this) || !isDumpsysTaskEnabled(getContentResolver())) {
             jobFinished(params, true);
             return false;
         }
@@ -105,6 +107,12 @@
     }
 
     @VisibleForTesting
+    static boolean isDumpsysTaskEnabled(ContentResolver resolver) {
+        // The default is to treat the task as enabled.
+        return Settings.Global.getInt(resolver, Settings.Global.ENABLE_DISKSTATS_LOGGING, 1) != 0;
+    }
+
+    @VisibleForTesting
     static class LogRunnable implements Runnable {
         private static final long TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(10);
 
diff --git a/services/core/java/com/android/server/storage/FileCollector.java b/services/core/java/com/android/server/storage/FileCollector.java
index 90f9f139..59cfaf7 100644
--- a/services/core/java/com/android/server/storage/FileCollector.java
+++ b/services/core/java/com/android/server/storage/FileCollector.java
@@ -26,7 +26,6 @@
 import java.io.File;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.util.Map;
 
 /**
  * FileCollector walks over a directory and categorizes storage usage by their type.
@@ -44,8 +43,9 @@
             AUDIO })
     private @interface FileTypes {}
 
-
-    private static final Map<String, Integer> EXTENSION_MAP = new ArrayMap<String, Integer>();
+    // NOTE: If you update these extensions, you'll also want to update
+    // matchgen.py over in installd which is used for non-quota stats.
+    private static final ArrayMap<String, Integer> EXTENSION_MAP = new ArrayMap<>();
     static {
         // Audio
         EXTENSION_MAP.put("aac", AUDIO);
@@ -144,6 +144,36 @@
         EXTENSION_MAP.put("xwd", IMAGES);
     }
 
+    private static File mkdir(File parent, String name) {
+        final File file = new File(parent, name);
+        file.mkdir();
+        return file;
+    }
+
+    /**
+     * Update the mapping used by sdcardfs to map from file extensions to GIDs
+     * used for statistics purposes.
+     */
+    public static void updateKernelExtensions() {
+        final File root = new File("/config/sdcardfs/extensions/");
+        if (!root.exists()) return;
+
+        final File audio = mkdir(root, Integer.toString(android.os.Process.MEDIA_AUDIO_GID));
+        final File video = mkdir(root, Integer.toString(android.os.Process.MEDIA_VIDEO_GID));
+        final File image = mkdir(root, Integer.toString(android.os.Process.MEDIA_IMAGE_GID));
+
+        for (int i = 0; i < EXTENSION_MAP.size(); i++) {
+            final String ext = EXTENSION_MAP.keyAt(i);
+            final int type = EXTENSION_MAP.valueAt(i);
+
+            switch (type) {
+                case AUDIO: mkdir(audio, ext); break;
+                case VIDEO: mkdir(video, ext); break;
+                case IMAGES: mkdir(image, ext); break;
+            }
+        }
+    }
+
     /**
      * Returns the file categorization measurement result.
      * @param path Directory to collect and categorize storage in.
diff --git a/services/core/java/com/android/server/text/TextClassificationService.java b/services/core/java/com/android/server/text/TextClassificationService.java
new file mode 100644
index 0000000..9358238
--- /dev/null
+++ b/services/core/java/com/android/server/text/TextClassificationService.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.server.text;
+
+import android.content.Context;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.text.ITextClassificationService;
+import android.util.Slog;
+
+import com.android.server.SystemService;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+/**
+ * Text classification service.
+ * This is used to provide access to the text classification LSTM model file.
+ */
+public class TextClassificationService extends ITextClassificationService.Stub {
+
+    private static final String LOG_TAG = "TextClassificationService";
+
+    public static final class Lifecycle extends SystemService {
+
+        private TextClassificationService mService;
+
+        public Lifecycle(Context context) {
+            super(context);
+            mService = new TextClassificationService();
+        }
+
+        @Override
+        public void onStart() {
+            try {
+                publishBinderService(Context.TEXT_CLASSIFICATION_SERVICE, mService);
+            } catch (Throwable t) {
+                // Starting this service is not critical to the running of this device and should
+                // therefore not crash the device. If it fails, log the error and continue.
+                Slog.e(LOG_TAG, "Could not start the TextClassificationService.", t);
+            }
+        }
+    }
+
+    @Override
+    public synchronized ParcelFileDescriptor getModelFileFd() throws RemoteException {
+        try {
+            return ParcelFileDescriptor.open(
+                    new File("/etc/assistant/smart-selection.model"),
+                    ParcelFileDescriptor.MODE_READ_ONLY);
+        } catch (Throwable t) {
+            Slog.e(LOG_TAG, "Error retrieving an fd to the text classification model file.", t);
+            throw new RemoteException(t.getMessage());
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 57587b0..e8385fc 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -88,9 +88,9 @@
  * {@link android.app.Activity#setVrModeEnabled)}.  An application may also implement a service to
  * be run while in VR mode by implementing {@link android.service.vr.VrListenerService}.
  *
- * @see {@link android.service.vr.VrListenerService}
- * @see {@link com.android.server.vr.VrManagerInternal}
- * @see {@link com.android.server.vr.VrStateListener}
+ * @see android.service.vr.VrListenerService
+ * @see com.android.server.vr.VrManagerInternal
+ * @see com.android.server.vr.VrStateListener
  *
  * @hide
  */
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 27e0f29..3a86874 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -41,6 +41,7 @@
 import android.view.IApplicationToken;
 import android.view.WindowManagerPolicy.StartingSurface;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.AttributeCache;
 /**
  * Controller for the app window token container. This is created by activity manager to link
@@ -202,7 +203,7 @@
                         + " controller=" + taskController);
             }
 
-            atoken = new AppWindowToken(mService, token, voiceInteraction, task.getDisplayContent(),
+            atoken = createAppWindow(mService, token, voiceInteraction, task.getDisplayContent(),
                     inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdkVersion,
                     requestedOrientation, rotationAnimationHint, configChanges, launchTaskBehind,
                     alwaysFocusable, this);
@@ -212,6 +213,18 @@
         }
     }
 
+    @VisibleForTesting
+    AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
+            boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
+            boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
+            int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
+            boolean alwaysFocusable, AppWindowContainerController controller) {
+        return  new AppWindowToken(service, token, voiceInteraction, dc,
+                inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk, orientation,
+                rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
+                controller);
+    }
+
     public void removeContainer(int displayId) {
         synchronized(mWindowMap) {
             final DisplayContent dc = mRoot.getDisplayContent(displayId);
@@ -230,6 +243,25 @@
         throw new UnsupportedOperationException("Use removeContainer(displayId) instead.");
     }
 
+    public void reparent(TaskWindowContainerController taskController, int position) {
+        synchronized (mWindowMap) {
+            if (DEBUG_ADD_REMOVE) Slog.i(TAG_WM, "reparent: moving app token=" + mToken
+                    + " to task=" + taskController + " at " + position);
+            if (mContainer == null) {
+                if (DEBUG_ADD_REMOVE) Slog.i(TAG_WM,
+                        "reparent: could not find app token=" + mToken);
+                return;
+            }
+            final Task task = taskController.mContainer;
+            if (task == null) {
+                throw new IllegalArgumentException("reparent: could not find task="
+                        + taskController);
+            }
+            mContainer.reparent(task, position);
+            mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
+        }
+    }
+
     public Configuration setOrientation(int requestedOrientation, int displayId,
             Configuration displayConfig, boolean freezeScreenIfNeeded) {
         synchronized(mWindowMap) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 079dc8f..bcc720d 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -850,6 +850,27 @@
         }
     }
 
+    void reparent(Task task, int position) {
+        if (task == mTask) {
+            throw new IllegalArgumentException(
+                    "window token=" + this + " already child of task=" + mTask);
+        }
+        if (DEBUG_ADD_REMOVE) Slog.i(TAG, "reParentWindowToken: removing window token=" + this
+                + " from task=" + mTask);
+        final DisplayContent prevDisplayContent = getDisplayContent();
+
+        getParent().removeChild(this);
+        task.addChild(this, position);
+
+        // Relayout display(s).
+        final DisplayContent displayContent = task.getDisplayContent();
+        displayContent.setLayoutNeeded();
+        if (prevDisplayContent != displayContent) {
+            onDisplayChanged(displayContent);
+            prevDisplayContent.setLayoutNeeded();
+        }
+    }
+
     private boolean canFreezeBounds() {
         // For freeform windows, we can't freeze the bounds at the moment because this would make
         // the resizing unresponsive.
diff --git a/services/core/java/com/android/server/wm/DimLayerController.java b/services/core/java/com/android/server/wm/DimLayerController.java
index 2ec2dba..3a6e328 100644
--- a/services/core/java/com/android/server/wm/DimLayerController.java
+++ b/services/core/java/com/android/server/wm/DimLayerController.java
@@ -322,6 +322,9 @@
             }
             mState.remove(dimLayerUser);
         }
+        if (mState.isEmpty()) {
+            mSharedFullScreenDimLayer = null;
+        }
     }
 
     @VisibleForTesting
@@ -329,6 +332,11 @@
         return mState.containsKey(dimLayerUser);
     }
 
+    @VisibleForTesting
+    boolean hasSharedFullScreenDimLayer() {
+        return mSharedFullScreenDimLayer != null;
+    }
+
     void applyDimBehind(DimLayer.DimLayerUser dimLayerUser, WindowStateAnimator animator) {
         applyDim(dimLayerUser, animator, false /* aboveApp */);
     }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 3a74ded..679f178 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -627,6 +627,8 @@
     };
 
     /**
+     * Create new {@link DisplayContent} instance, add itself to the root window container and
+     * initialize direct children.
      * @param display May not be null.
      * @param service You know.
      * @param layersController window layer controller used to assign layer to the windows on this
@@ -661,6 +663,9 @@
         super.addChild(mTaskStackContainers, null);
         super.addChild(mAboveAppWindowsContainers, null);
         super.addChild(mImeWindowsContainers, null);
+
+        // Add itself as a child to the root container.
+        mService.mRoot.addChild(this, null);
     }
 
     int getDisplayId() {
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index aaf724e..5a2ee9a 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -102,12 +102,14 @@
     private int mDividerWindowWidth;
     private int mDividerWindowWidthInactive;
     private int mDividerInsets;
+    private int mTaskHeightInMinimizedMode;
     private boolean mResizing;
     private WindowState mWindow;
     private final Rect mTmpRect = new Rect();
     private final Rect mTmpRect2 = new Rect();
     private final Rect mTmpRect3 = new Rect();
     private final Rect mLastRect = new Rect();
+    private final Rect mMiddlePositionDockedStackRect = new Rect();
     private boolean mLastVisibility = false;
     private final RemoteCallbackList<IDockedStackListener> mDockedStackListeners
             = new RemoteCallbackList<>();
@@ -189,6 +191,40 @@
         return (int) (minWidth / mDisplayContent.getDisplayMetrics().density);
     }
 
+    /**
+     * The middlePositionDockedStackRect is half the screen area that sits at the top (portrait) or
+     * left (landscape).
+     *
+     * @return fixed rect for temp stack
+     */
+    Rect getMiddlePositionDockedStackRect() {
+        return mMinimizedDock && isHomeStackResizable() ? mMiddlePositionDockedStackRect : null;
+    }
+
+    void getHomeStackBoundsInDockedMode(Rect outBounds) {
+        final DisplayInfo di = mDisplayContent.getDisplayInfo();
+        mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
+                mTmpRect);
+        int dividerSize = mDividerWindowWidth - 2 * mDividerInsets;
+        Configuration configuration = mDisplayContent.getConfiguration();
+        if (configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
+            outBounds.set(0, mTaskHeightInMinimizedMode + dividerSize + mTmpRect.top,
+                    di.logicalWidth, di.logicalHeight);
+        } else {
+            outBounds.set(mTaskHeightInMinimizedMode + dividerSize + mTmpRect.left, 0,
+                    di.logicalWidth, di.logicalHeight);
+        }
+    }
+
+    boolean isHomeStackResizable() {
+        final TaskStack homeStack = mDisplayContent.getHomeStack();
+        if (homeStack == null) {
+            return false;
+        }
+        final Task homeTask = homeStack.findHomeTask();
+        return homeTask != null && homeTask.isResizeable();
+    }
+
     private void initSnapAlgorithmForRotations() {
         final Configuration baseConfig = mDisplayContent.getConfiguration();
 
@@ -228,11 +264,34 @@
                 com.android.internal.R.dimen.docked_stack_divider_insets);
         mDividerWindowWidthInactive = WindowManagerService.dipToPixel(
                 DIVIDER_WIDTH_INACTIVE_DP, mDisplayContent.getDisplayMetrics());
+        mTaskHeightInMinimizedMode = context.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.task_height_of_minimized_mode);
         initSnapAlgorithmForRotations();
     }
 
+    /**
+     * Calculates the constant rects {@link mMiddlePositionDockedStackRect} based on orientation,
+     * stable insets and display size.
+     */
+    private void updateConstantRects() {
+        final DisplayInfo di = mDisplayContent.getDisplayInfo();
+        mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
+                mTmpRect);
+        int dividerSize = mDividerWindowWidth - 2 * mDividerInsets;
+        Configuration configuration = mDisplayContent.getConfiguration();
+        boolean isHorizontal = configuration.orientation == Configuration.ORIENTATION_PORTRAIT;
+        int middlePosition = DockedDividerUtils.calculateMiddlePosition(isHorizontal, mTmpRect,
+                di.logicalWidth, di.logicalHeight, dividerSize);
+        if (isHorizontal) {
+            mMiddlePositionDockedStackRect.set(0, 0, di.logicalWidth, middlePosition);
+        } else {
+            mMiddlePositionDockedStackRect.set(0, 0, middlePosition, di.logicalHeight);
+        }
+    }
+
     void onConfigurationChanged() {
         loadDimens();
+        updateConstantRects();
     }
 
     boolean isResizing() {
@@ -412,7 +471,19 @@
         return mImeHideRequested;
     }
 
-    private void notifyDockedStackMinimizedChanged(boolean minimizedDock, long animDuration) {
+    private void notifyDockedStackMinimizedChanged(boolean minimizedDock, boolean animate,
+            boolean isHomeStackResizable) {
+        long animDuration = 0;
+        if (animate) {
+            final TaskStack stack = mDisplayContent.getStackById(DOCKED_STACK_ID);
+            final long transitionDuration = isAnimationMaximizing()
+                    ? mService.mAppTransition.getLastClipRevealTransitionDuration()
+                    : DEFAULT_APP_TRANSITION_DURATION;
+            mAnimationDuration = (long)
+                    (transitionDuration * mService.getTransitionAnimationScaleLocked());
+            mMaximizeMeetFraction = getClipRevealMeetFraction(stack);
+            animDuration = (long) (mAnimationDuration * mMaximizeMeetFraction);
+        }
         mService.mH.removeMessages(NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED);
         mService.mH.obtainMessage(NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED,
                 minimizedDock ? 1 : 0, 0).sendToTarget();
@@ -420,7 +491,8 @@
         for (int i = 0; i < size; ++i) {
             final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
             try {
-                listener.onDockedStackMinimizedChanged(minimizedDock, animDuration);
+                listener.onDockedStackMinimizedChanged(minimizedDock, animDuration,
+                        isHomeStackResizable);
             } catch (RemoteException e) {
                 Slog.e(TAG_WM, "Error delivering minimized dock changed event.", e);
             }
@@ -458,7 +530,8 @@
         mDockedStackListeners.register(listener);
         notifyDockedDividerVisibilityChanged(wasVisible());
         notifyDockedStackExistsChanged(mDisplayContent.getDockedStackIgnoringVisibility() != null);
-        notifyDockedStackMinimizedChanged(mMinimizedDock, 0 /* animDuration */);
+        notifyDockedStackMinimizedChanged(mMinimizedDock, false /* animate */,
+                isHomeStackResizable());
         notifyAdjustedForImeChanged(mAdjustedForIme, 0 /* animDuration */);
 
     }
@@ -577,17 +650,23 @@
 
         final boolean imeChanged = clearImeAdjustAnimation();
         boolean minimizedChange = false;
-        if (minimizedDock) {
-            if (animate) {
-                startAdjustAnimation(0f, 1f);
-            } else {
-                minimizedChange |= setMinimizedDockedStack(true);
-            }
+        if (isHomeStackResizable()) {
+            notifyDockedStackMinimizedChanged(minimizedDock, true /* animate */,
+                    true /* isHomeStackResizable */);
+            minimizedChange = true;
         } else {
-            if (animate) {
-                startAdjustAnimation(1f, 0f);
+            if (minimizedDock) {
+                if (animate) {
+                    startAdjustAnimation(0f, 1f);
+                } else {
+                    minimizedChange |= setMinimizedDockedStack(true);
+                }
             } else {
-                minimizedChange |= setMinimizedDockedStack(false);
+                if (animate) {
+                    startAdjustAnimation(1f, 0f);
+                } else {
+                    minimizedChange |= setMinimizedDockedStack(false);
+                }
             }
         }
         if (imeChanged || minimizedChange) {
@@ -688,7 +767,7 @@
 
     private boolean setMinimizedDockedStack(boolean minimized) {
         final TaskStack stack = mDisplayContent.getDockedStackIgnoringVisibility();
-        notifyDockedStackMinimizedChanged(minimized, 0);
+        notifyDockedStackMinimizedChanged(minimized, false /* animate */, isHomeStackResizable());
         return stack != null && stack.setAdjustedForMinimizedDock(minimized ? 1f : 0f);
     }
 
@@ -742,14 +821,8 @@
         if (!mAnimationStarted) {
             mAnimationStarted = true;
             mAnimationStartTime = now;
-            final long transitionDuration = isAnimationMaximizing()
-                    ? mService.mAppTransition.getLastClipRevealTransitionDuration()
-                    : DEFAULT_APP_TRANSITION_DURATION;
-            mAnimationDuration = (long)
-                    (transitionDuration * mService.getTransitionAnimationScaleLocked());
-            mMaximizeMeetFraction = getClipRevealMeetFraction(stack);
-            notifyDockedStackMinimizedChanged(mMinimizedDock,
-                    (long) (mAnimationDuration * mMaximizeMeetFraction));
+            notifyDockedStackMinimizedChanged(mMinimizedDock, true /* animate */,
+                    isHomeStackResizable() /* isHomeStackResizable */);
         }
         float t = Math.min(1f, (float) (now - mAnimationStartTime) / mAnimationDuration);
         t = (isAnimationMaximizing() ? TOUCH_RESPONSE_INTERPOLATOR : mMinimizedDockInterpolator)
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 36520a9..1ae987f 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -148,7 +148,7 @@
             mDragApplicationHandle.dispatchingTimeoutNanos =
                     WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
 
-            mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null,
+            mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null, null,
                     display.getDisplayId());
             mDragWindowHandle.name = "drag";
             mDragWindowHandle.inputChannel = mServerChannel;
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index 24783bc..b92bfb9 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -48,7 +48,8 @@
         mApplicationHandle.dispatchingTimeoutNanos =
                 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
 
-        mWindowHandle = new InputWindowHandle(mApplicationHandle, null, Display.DEFAULT_DISPLAY);
+        mWindowHandle = new InputWindowHandle(mApplicationHandle, null, null,
+                Display.DEFAULT_DISPLAY);
         mWindowHandle.name = name;
         mWindowHandle.inputChannel = mServerChannel;
         mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index f754775..5f53d84 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -77,6 +77,8 @@
     // Array of window handles to provide to the input dispatcher.
     private InputWindowHandle[] mInputWindowHandles;
     private int mInputWindowHandleCount;
+    private InputWindowHandle mFocusedInputWindowHandle;
+
     private boolean mAddInputConsumerHandle;
     private boolean mAddPipInputConsumerHandle;
     private boolean mAddWallpaperInputConsumerHandle;
@@ -327,12 +329,16 @@
                     + child + ", " + inputWindowHandle);
         }
         addInputWindowHandle(inputWindowHandle);
+        if (hasFocus) {
+            mFocusedInputWindowHandle = inputWindowHandle;
+        }
     }
 
     private void clearInputWindowHandlesLw() {
         while (mInputWindowHandleCount != 0) {
             mInputWindowHandles[--mInputWindowHandleCount] = null;
         }
+        mFocusedInputWindowHandle = null;
     }
 
     void setUpdateInputWindowsNeededLw() {
@@ -609,7 +615,7 @@
             }
 
             // Send windows to native code.
-            mService.mInputManager.setInputWindows(mInputWindowHandles);
+            mService.mInputManager.setInputWindows(mInputWindowHandles, mFocusedInputWindowHandle);
 
             clearInputWindowHandlesLw();
         }
@@ -619,7 +625,7 @@
             final InputChannel inputChannel = w.mInputChannel;
             final InputWindowHandle inputWindowHandle = w.mInputWindowHandle;
             if (inputChannel == null || inputWindowHandle == null || w.mRemoved
-                    || w.isAdjustedForMinimizedDock()) {
+                    || w.canReceiveTouchInput()) {
                 // Skip this window because it cannot possibly receive input.
                 return;
             }
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 08f9b45..596c3d8 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -114,6 +114,7 @@
         public void setIsMinimized(final boolean isMinimized) {
             mHandler.post(() -> {
                 mIsMinimized = isMinimized;
+                mSnapAlgorithm.setMinimized(isMinimized);
             });
         }
 
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 22abf30..80e6655 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -213,7 +213,6 @@
         final int displayId = display.getDisplayId();
 
         if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
-        addChild(dc, null);
 
         final DisplayInfo displayInfo = dc.getDisplayInfo();
         final Rect rect = new Rect();
diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java
index 9a6f3eb5..e2ea2c5 100644
--- a/services/core/java/com/android/server/wm/StackWindowController.java
+++ b/services/core/java/com/android/server/wm/StackWindowController.java
@@ -220,13 +220,17 @@
         }
     }
 
-    public void getStackDockedModeBounds(Rect outBounds, boolean ignoreVisibility) {
+    public void getStackDockedModeBounds(Rect outBounds, Rect outTempBounds,
+            Rect outTempInsetBounds, boolean ignoreVisibility) {
         synchronized (mWindowMap) {
             if (mContainer != null) {
-                mContainer.getStackDockedModeBoundsLocked(outBounds, ignoreVisibility);
+                mContainer.getStackDockedModeBoundsLocked(outBounds, outTempBounds,
+                        outTempInsetBounds, ignoreVisibility);
                 return;
             }
             outBounds.setEmpty();
+            outTempBounds.setEmpty();
+            outTempInsetBounds.setEmpty();
         }
     }
 
@@ -269,11 +273,9 @@
         }
     }
 
-    public Rect getBoundsForNewConfiguration() {
+    public void getBoundsForNewConfiguration(Rect outBounds, Rect outTempBounds) {
         synchronized(mWindowMap) {
-            final Rect outBounds = new Rect();
-            mContainer.getBoundsForNewConfiguration(outBounds);
-            return outBounds;
+            mContainer.getBoundsForNewConfiguration(outBounds, outTempBounds);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 7bc577e..90106a9 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -269,7 +269,7 @@
         mDragApplicationHandle.dispatchingTimeoutNanos =
                 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
 
-        mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null,
+        mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null, null,
                 mDisplay.getDisplayId());
         mDragWindowHandle.name = TAG;
         mDragWindowHandle.inputChannel = mServerChannel;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index d3eae8c..0ff1f0c 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -213,7 +213,7 @@
         mAdjustedBounds.set(bounds);
         final boolean adjusted = !mAdjustedBounds.isEmpty();
         Rect insetBounds = null;
-        if (adjusted && isAdjustedForMinimizedDock()) {
+        if (adjusted && isAdjustedForMinimizedDockedStack()) {
             insetBounds = mBounds;
         } else if (adjusted && mAdjustedForIme) {
             if (mImeGoingAway) {
@@ -420,9 +420,14 @@
         return true;
     }
 
-    void getBoundsForNewConfiguration(Rect outBounds) {
+    void getBoundsForNewConfiguration(Rect outBounds, Rect outTempBounds) {
         outBounds.set(mBoundsAfterRotation);
         mBoundsAfterRotation.setEmpty();
+        final DockedStackDividerController controller = getDisplayContent()
+                .mDividerControllerLocked;
+        if (controller.isMinimizedDock() && mStackId == DOCKED_STACK_ID) {
+            outTempBounds.set(controller.getMiddlePositionDockedStackRect());
+        }
     }
 
     /**
@@ -482,7 +487,8 @@
         mService.mPolicy.getStableInsetsLw(rotation, displayWidth, displayHeight, outBounds);
         final DividerSnapAlgorithm algorithm = new DividerSnapAlgorithm(
                 mService.mContext.getResources(), displayWidth, displayHeight,
-                dividerSize, orientation == Configuration.ORIENTATION_PORTRAIT, outBounds);
+                dividerSize, orientation == Configuration.ORIENTATION_PORTRAIT, outBounds,
+                isMinimizedDockAndHomeStackResizable());
         final SnapTarget target = algorithm.calculateNonDismissingSnapTarget(dividerPosition);
 
         // Recalculate the bounds based on the position of the target.
@@ -675,7 +681,18 @@
         super.onDisplayChanged(dc);
     }
 
-    void getStackDockedModeBoundsLocked(Rect outBounds, boolean ignoreVisibility) {
+    void getStackDockedModeBoundsLocked(Rect outBounds, Rect outTempBounds,
+            Rect outTempInsetBounds, boolean ignoreVisibility) {
+        if (mStackId == HOME_STACK_ID && findHomeTask().isResizeable()) {
+            // Calculate the home stack bounds when in docked mode
+            getDisplayContent().mDividerControllerLocked
+                    .getHomeStackBoundsInDockedMode(outTempBounds);
+            outTempInsetBounds.set(outTempBounds);
+        } else {
+            outTempBounds.setEmpty();
+            outTempInsetBounds.setEmpty();
+        }
+
         if ((mStackId != DOCKED_STACK_ID && !StackId.isResizeableByDockedStack(mStackId))
                 || mDisplayContent == null) {
             outBounds.set(mBounds);
@@ -789,7 +806,9 @@
         mService.mDockedStackCreateBounds = null;
 
         final Rect bounds = new Rect();
-        getStackDockedModeBoundsLocked(bounds, true /*ignoreVisibility*/);
+        final Rect tempBounds = new Rect();
+        final Rect tempInsetBounds = new Rect();
+        getStackDockedModeBoundsLocked(bounds, tempBounds, tempInsetBounds, true /*ignoreVisibility*/);
         getController().requestResize(bounds);
     }
 
@@ -946,8 +965,9 @@
         }
     }
 
-    boolean isAdjustedForMinimizedDock() {
-        return mMinimizeAmount != 0f;
+    boolean shouldIgnoreInput() {
+        return isAdjustedForMinimizedDockedStack() || mStackId == DOCKED_STACK_ID &&
+                isMinimizedDockAndHomeStackResizable();
     }
 
     /**
@@ -1075,6 +1095,11 @@
         return true;
     }
 
+    private boolean isMinimizedDockAndHomeStackResizable() {
+        return mDisplayContent.mDividerControllerLocked.isMinimizedDock()
+                && mDisplayContent.mDividerControllerLocked.isHomeStackResizable();
+    }
+
     /**
      * @return the distance in pixels how much the stack gets minimized from it's original size
      */
@@ -1344,9 +1369,17 @@
              * tasks (including the focused).
              *
              * We save the focused task region once we find it, and add it back at the end.
+             *
+             * If the task is home stack and it is resizable in the minimized state, we want to
+             * exclude the docked stack from touch so we need the entire screen area and not just a
+             * small portion which the home stack currently is resized to.
              */
 
-            task.getDimBounds(mTmpRect);
+            if (task.isHomeTask() && isMinimizedDockAndHomeStackResizable()) {
+                mDisplayContent.getLogicalDisplayRect(mTmpRect);
+            } else {
+                task.getDimBounds(mTmpRect);
+            }
 
             if (task == focusedTask) {
                 // Add the focused task rect back into the exclude region once we are done
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 1987f90..d62c62e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -4826,6 +4826,14 @@
                 mDisplayMetrics, dw, dh, displayId);
         config.densityDpi = displayInfo.logicalDensityDpi;
 
+        config.colorMode =
+                (displayInfo.isHdr()
+                        ? Configuration.COLOR_MODE_HDR_YES
+                        : Configuration.COLOR_MODE_HDR_NO)
+                | (displayInfo.isWideColorGamut()
+                        ? Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_YES
+                        : Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_NO);
+
         // Update the configuration based on available input devices, lid switch,
         // and platform configuration.
         config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 5e458d4..050adfe 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -657,7 +657,8 @@
         mYOffset = 0;
         mLayer = 0;
         mInputWindowHandle = new InputWindowHandle(
-                mAppToken != null ? mAppToken.mInputApplicationHandle : null, this, getDisplayId());
+                mAppToken != null ? mAppToken.mInputApplicationHandle : null, this, c,
+                    getDisplayId());
     }
 
     void attach() {
@@ -1671,11 +1672,6 @@
         return !mLastReportedConfiguration.equals(getConfiguration());
     }
 
-    boolean isAdjustedForMinimizedDock() {
-        return mAppToken != null && mAppToken.mTask != null
-                && mAppToken.mTask.mStack.isAdjustedForMinimizedDock();
-    }
-
     void onWindowReplacementTimeout() {
         if (mWillReplaceWindow) {
             // Since the window already timed out, remove it immediately now.
@@ -2364,7 +2360,13 @@
                 && (mViewVisibility == View.VISIBLE) && !mRemoveOnExit
                 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0)
                 && (mAppToken == null || mAppToken.windowsAreFocusable())
-                && !isAdjustedForMinimizedDock();
+                && !canReceiveTouchInput();
+    }
+
+    /** @return true if this window desires touch events. */
+    boolean canReceiveTouchInput() {
+        return mAppToken != null && mAppToken.mTask != null
+                && mAppToken.mTask.mStack.shouldIgnoreInput();
     }
 
     @Override
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 6791da9..8baa96b 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -207,6 +207,7 @@
     void setPointerIconType(int32_t iconId);
     void reloadPointerIcons();
     void setCustomPointerIcon(const SpriteIcon& icon);
+    void setPointerCapture(bool enabled);
 
     /* --- InputReaderPolicyInterface implementation --- */
 
@@ -276,6 +277,9 @@
         // Show touches feature enable/disable.
         bool showTouches;
 
+        // Pointer capture feature enable/disable.
+        bool pointerCapture;
+
         // Sprite controller singleton, created on first use.
         sp<SpriteController> spriteController;
 
@@ -312,6 +316,7 @@
         mLocked.pointerSpeed = 0;
         mLocked.pointerGesturesEnabled = true;
         mLocked.showTouches = false;
+        mLocked.pointerCapture = false;
     }
     mInteractive = true;
 
@@ -339,6 +344,7 @@
         dump.appendFormat(INDENT "Pointer Gestures Enabled: %s\n",
                 toString(mLocked.pointerGesturesEnabled));
         dump.appendFormat(INDENT "Show Touches: %s\n", toString(mLocked.showTouches));
+        dump.appendFormat(INDENT "Pointer Capture Enabled: %s\n", toString(mLocked.pointerCapture));
     }
     dump.append("\n");
 
@@ -460,6 +466,8 @@
 
         outConfig->showTouches = mLocked.showTouches;
 
+        outConfig->pointerCapture = mLocked.pointerCapture;
+
         outConfig->setDisplayInfo(false /*external*/, mLocked.internalViewport);
         outConfig->setDisplayInfo(true /*external*/, mLocked.externalViewport);
     } // release lock
@@ -767,6 +775,22 @@
             InputReaderConfiguration::CHANGE_SHOW_TOUCHES);
 }
 
+void NativeInputManager::setPointerCapture(bool enabled) {
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        if (mLocked.pointerCapture == enabled) {
+            return;
+        }
+
+        ALOGI("Setting pointer capture to %s.", enabled ? "enabled" : "disabled");
+        mLocked.pointerCapture = enabled;
+    } // release lock
+
+    mInputManager->getReader()->requestRefreshConfiguration(
+            InputReaderConfiguration::CHANGE_POINTER_CAPTURE);
+}
+
 void NativeInputManager::setInteractive(bool interactive) {
     mInteractive = interactive;
 }
@@ -1323,6 +1347,12 @@
     im->setFocusedApplication(env, applicationHandleObj);
 }
 
+static void nativeSetPointerCapture(JNIEnv* env, jclass /* clazz */, jlong ptr,
+        jboolean enabled) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+    im->setPointerCapture(enabled);
+}
+
 static void nativeSetInputDispatchMode(JNIEnv* /* env */,
         jclass /* clazz */, jlong ptr, jboolean enabled, jboolean frozen) {
     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
@@ -1509,6 +1539,8 @@
             (void*) nativeSetInputWindows },
     { "nativeSetFocusedApplication", "(JLcom/android/server/input/InputApplicationHandle;)V",
             (void*) nativeSetFocusedApplication },
+    { "nativeSetPointerCapture", "(JZ)V",
+            (void*) nativeSetPointerCapture },
     { "nativeSetInputDispatchMode", "(JZZ)V",
             (void*) nativeSetInputDispatchMode },
     { "nativeSetSystemUiVisibility", "(JI)V",
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 7558e3c..3c1d274 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1531,6 +1531,10 @@
             return (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
         }
 
+        AlarmManager getAlarmManager() {
+            return (AlarmManager) mContext.getSystemService(AlarmManager.class);
+        }
+
         IWindowManager getIWindowManager() {
             return IWindowManager.Stub
                     .asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
@@ -2091,7 +2095,7 @@
         long token = mInjector.binderClearCallingIdentity();
         try {
             int affectedUserHandle = parent ? getProfileParentId(userHandle) : userHandle;
-            AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+            AlarmManager am = mInjector.getAlarmManager();
             PendingIntent pi = PendingIntent.getBroadcastAsUser(context, REQUEST_EXPIRE_PASSWORD,
                     new Intent(ACTION_EXPIRED_PASSWORD_NOTIFICATION),
                     PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT,
@@ -4892,12 +4896,13 @@
             // Notify delegate package of updates.
             final Intent intent = new Intent(
                     DevicePolicyManager.ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED);
-            // Only call receivers registered in the manifest (don’t wake app if not running).
+            // Only call receivers registered with Context#registerReceiver (don’t wake delegate).
             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
             // Limit components this intent resolves to to the delegate package.
             intent.setPackage(delegatePackage);
             // Include the list of delegated scopes as an extra.
-            intent.putExtra(DevicePolicyManager.EXTRA_DELEGATION_SCOPES, scopes.toArray());
+            intent.putStringArrayListExtra(DevicePolicyManager.EXTRA_DELEGATION_SCOPES,
+                    (ArrayList<String>) scopes);
             // Send the broadcast.
             mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
 
@@ -8957,18 +8962,20 @@
 
             ComponentName profileOwner = mOwners.getProfileOwnerComponent(userId);
             if (profileOwner != null) {
-                return createShowAdminSupportIntent(profileOwner, userId);
+                return DevicePolicyManagerService.this
+                        .createShowAdminSupportIntent(profileOwner, userId);
             }
 
             final Pair<Integer, ComponentName> deviceOwner =
                     mOwners.getDeviceOwnerUserIdAndComponent();
             if (deviceOwner != null && deviceOwner.first == userId) {
-                return createShowAdminSupportIntent(deviceOwner.second, userId);
+                return DevicePolicyManagerService.this
+                        .createShowAdminSupportIntent(deviceOwner.second, userId);
             }
 
             // We're not specifying the device admin because there isn't one.
             if (useDefaultIfNoAdmin) {
-                return createShowAdminSupportIntent(null, userId);
+                return DevicePolicyManagerService.this.createShowAdminSupportIntent(null, userId);
             }
             return null;
         }
@@ -8996,11 +9003,12 @@
             if (enforcedByDo && enforcedByPo) {
                 // In this case, we'll show an admin support dialog that does not
                 // specify the admin.
-                return createShowAdminSupportIntent(null, userId);
+                return DevicePolicyManagerService.this.createShowAdminSupportIntent(null, userId);
             } else if (enforcedByPo) {
                 final ComponentName profileOwner = mOwners.getProfileOwnerComponent(userId);
                 if (profileOwner != null) {
-                    return createShowAdminSupportIntent(profileOwner, userId);
+                    return DevicePolicyManagerService.this
+                            .createShowAdminSupportIntent(profileOwner, userId);
                 }
                 // This could happen if another thread has changed the profile owner since we called
                 // getUserRestrictionSource
@@ -9009,7 +9017,8 @@
                 final Pair<Integer, ComponentName> deviceOwner
                         = mOwners.getDeviceOwnerUserIdAndComponent();
                 if (deviceOwner != null) {
-                    return createShowAdminSupportIntent(deviceOwner.second, deviceOwner.first);
+                    return DevicePolicyManagerService.this
+                            .createShowAdminSupportIntent(deviceOwner.second, deviceOwner.first);
                 }
                 // This could happen if another thread has changed the device owner since we called
                 // getUserRestrictionSource
@@ -9017,15 +9026,57 @@
             }
             return null;
         }
+    }
 
-        private Intent createShowAdminSupportIntent(ComponentName admin, int userId) {
-            // This method is called with AMS lock held, so don't take DPMS lock
-            final Intent intent = new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS);
-            intent.putExtra(Intent.EXTRA_USER_ID, userId);
-            intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            return intent;
+    private Intent createShowAdminSupportIntent(ComponentName admin, int userId) {
+        // This method is called with AMS lock held, so don't take DPMS lock
+        final Intent intent = new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS);
+        intent.putExtra(Intent.EXTRA_USER_ID, userId);
+        intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, admin);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        return intent;
+    }
+
+    @Override
+    public Intent createAdminSupportIntent(String restriction) {
+        Preconditions.checkNotNull(restriction);
+        final int uid = mInjector.binderGetCallingUid();
+        final int userId = UserHandle.getUserId(uid);
+        Intent intent = null;
+        if (DevicePolicyManager.POLICY_DISABLE_CAMERA.equals(restriction) ||
+                DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE.equals(restriction)) {
+            synchronized(this) {
+                final DevicePolicyData policy = getUserData(userId);
+                final int N = policy.mAdminList.size();
+                for (int i = 0; i < N; i++) {
+                    final ActiveAdmin admin = policy.mAdminList.get(i);
+                    if ((admin.disableCamera &&
+                                DevicePolicyManager.POLICY_DISABLE_CAMERA.equals(restriction)) ||
+                        (admin.disableScreenCapture && DevicePolicyManager
+                                .POLICY_DISABLE_SCREEN_CAPTURE.equals(restriction))) {
+                        intent = createShowAdminSupportIntent(admin.info.getComponent(), userId);
+                        break;
+                    }
+                }
+                // For the camera, a device owner on a different user can disable it globally,
+                // so we need an additional check.
+                if (intent == null
+                        && DevicePolicyManager.POLICY_DISABLE_CAMERA.equals(restriction)) {
+                    final ActiveAdmin admin = getDeviceOwnerAdminLocked();
+                    if (admin != null && admin.disableCamera) {
+                        intent = createShowAdminSupportIntent(admin.info.getComponent(),
+                                mOwners.getDeviceOwnerUserId());
+                    }
+                }
+            }
+        } else {
+            // if valid, |restriction| can only be a user restriction
+            intent = mLocalService.createUserRestrictionSupportIntent(userId, restriction);
         }
+        if (intent != null) {
+            intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, restriction);
+        }
+        return intent;
     }
 
     /**
@@ -9246,11 +9297,12 @@
         PackageManager packageManager = mInjector.getPackageManager();
 
         UserHandle user = mInjector.binderGetCallingUserHandle();
-        enforceProfileOwnerOrSystemUser(admin);
-        synchronized (this) {
+        if (!isCallerWithSystemUid()) {
             // Ensure the caller is a DO/PO or a permission grant state delegate.
-            enforceCanManageScope(admin, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
-                    DELEGATION_PERMISSION_GRANT);
+            enforceCanManageScope(admin, callerPackage,
+                    DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, DELEGATION_PERMISSION_GRANT);
+        }
+        synchronized (this) {
             long ident = mInjector.binderClearCallingIdentity();
             try {
                 int granted = mIPackageManager.checkPermission(permission,
@@ -9856,7 +9908,7 @@
     private boolean areAllUsersAffiliatedWithDeviceLocked() {
         final long ident = mInjector.binderClearCallingIdentity();
         try {
-            final List<UserInfo> userInfos = mUserManager.getUsers();
+            final List<UserInfo> userInfos = mUserManager.getUsers(/*excludeDying=*/ true);
             for (int i = 0; i < userInfos.size(); i++) {
                 int userId = userInfos.get(i).id;
                 if (!isUserAffiliatedWithDeviceLocked(userId)) {
@@ -10264,47 +10316,51 @@
             return Collections.emptyList();
         }
         Preconditions.checkNotNull(admin);
-        ArrayList<UserHandle> targetUsers = new ArrayList<>();
 
         synchronized (this) {
-            ActiveAdmin callingOwner = getActiveAdminForCallerLocked(
-                    admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
 
             final int callingUserId = mInjector.userHandleGetCallingUserId();
-            final boolean isCallerDeviceOwner = isDeviceOwner(callingOwner);
-            final boolean isCallerManagedProfile = isManagedProfile(callingUserId);
-            if ((!isCallerDeviceOwner && !isCallerManagedProfile)
-                    || !isUserAffiliatedWithDeviceLocked(callingUserId)) {
-                return targetUsers;
-            }
-
             final long callingIdentity = mInjector.binderClearCallingIdentity();
             try {
-                String callingOwnerPackage = callingOwner.info.getComponent().getPackageName();
-                for (int userId : mUserManager.getProfileIdsWithDisabled(callingUserId)) {
-                    if (userId == callingUserId) {
-                        continue;
+                ArrayList<UserHandle> targetUsers = new ArrayList<>();
+                if (!isDeviceOwner(admin, callingUserId)) {
+                    // Profile owners can only bind to the device owner.
+                    if (canUserBindToDeviceOwnerLocked(callingUserId)) {
+                        targetUsers.add(UserHandle.of(mOwners.getDeviceOwnerUserId()));
                     }
-
-                    // We only allow the device owner and a managed profile owner to bind to each
-                    // other.
-                    if ((isCallerManagedProfile && userId == mOwners.getDeviceOwnerUserId())
-                            || (isCallerDeviceOwner && isManagedProfile(userId))) {
-                        String targetOwnerPackage = getOwnerPackageNameForUserLocked(userId);
-
-                        // Both must be the same package and be affiliated in order to bind.
-                        if (callingOwnerPackage.equals(targetOwnerPackage)
-                               && isUserAffiliatedWithDeviceLocked(userId)) {
+                } else {
+                    // Caller is the device owner: Look for profile owners that it can bind to.
+                    final List<UserInfo> userInfos = mUserManager.getUsers(/*excludeDying=*/ true);
+                    for (int i = 0; i < userInfos.size(); i++) {
+                        final int userId = userInfos.get(i).id;
+                        if (userId != callingUserId && canUserBindToDeviceOwnerLocked(userId)) {
                             targetUsers.add(UserHandle.of(userId));
                         }
                     }
                 }
+
+                return targetUsers;
             } finally {
                 mInjector.binderRestoreCallingIdentity(callingIdentity);
             }
         }
+    }
 
-        return targetUsers;
+    private boolean canUserBindToDeviceOwnerLocked(int userId) {
+        // There has to be a device owner, under another user id.
+        if (!mOwners.hasDeviceOwner() || userId == mOwners.getDeviceOwnerUserId()) {
+            return false;
+        }
+
+        // The user must have a profile owner that belongs to the same package as the device owner.
+        if (!mOwners.hasProfileOwner(userId) || !TextUtils.equals(
+                mOwners.getDeviceOwnerPackageName(), mOwners.getProfileOwnerPackage(userId))) {
+            return false;
+        }
+
+        // The user must be affiliated.
+        return isUserAffiliatedWithDeviceLocked(userId);
     }
 
     /**
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java
index 7d68412..9b4de043 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java
@@ -16,12 +16,15 @@
 
 package com.android.server.devicepolicy;
 
+import android.app.AlarmManager;
+import android.app.AlarmManager.OnAlarmListener;
 import android.app.admin.DeviceAdminReceiver;
 import android.app.admin.NetworkEvent;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.SystemClock;
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
@@ -42,11 +45,26 @@
     // If this value changes, update DevicePolicyManager#retrieveNetworkLogs() javadoc
     private static final int MAX_EVENTS_PER_BATCH = 1200;
     private static final long BATCH_FINALIZATION_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(90);
+    private static final long BATCH_FINALIZATION_TIMEOUT_ALARM_INTERVAL_MS =
+            TimeUnit.MINUTES.toMillis(30);
 
-    static final int LOG_NETWORK_EVENT_MSG = 1;
-    static final int FINALIZE_BATCH_MSG = 2;
+    private static final String NETWORK_LOGGING_TIMEOUT_ALARM_TAG = "NetworkLogging.batchTimeout";
 
     private final DevicePolicyManagerService mDpm;
+    private final AlarmManager mAlarmManager;
+
+    private final OnAlarmListener mBatchTimeoutAlarmListener = new OnAlarmListener() {
+        @Override
+        public void onAlarm() {
+            Log.d(TAG, "Received a batch finalization timeout alarm, finalizing "
+                    + mNetworkEvents.size() + " pending events.");
+            synchronized (NetworkLoggingHandler.this) {
+                finalizeBatchAndNotifyDeviceOwnerLocked();
+            }
+        }
+    };
+
+    static final int LOG_NETWORK_EVENT_MSG = 1;
 
     // threadsafe as it's Handler's thread confined
     @GuardedBy("this")
@@ -68,6 +86,7 @@
     NetworkLoggingHandler(Looper looper, DevicePolicyManagerService dpm) {
         super(looper);
         mDpm = dpm;
+        mAlarmManager = mDpm.mInjector.getAlarmManager();
     }
 
     @Override
@@ -85,19 +104,19 @@
                 }
                 break;
             }
-            case FINALIZE_BATCH_MSG: {
-                synchronized (NetworkLoggingHandler.this) {
-                    finalizeBatchAndNotifyDeviceOwnerLocked();
-                }
+            default: {
+                Log.d(TAG, "NetworkLoggingHandler received an unknown of message.");
                 break;
             }
         }
     }
 
     void scheduleBatchFinalization() {
-        removeMessages(FINALIZE_BATCH_MSG);
-        sendMessageDelayed(obtainMessage(FINALIZE_BATCH_MSG), BATCH_FINALIZATION_TIMEOUT_MS);
-        Log.d(TAG, "Scheduled new batch finalization " + BATCH_FINALIZATION_TIMEOUT_MS
+        final long when = SystemClock.elapsedRealtime() + BATCH_FINALIZATION_TIMEOUT_MS;
+        mAlarmManager.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP, when,
+                BATCH_FINALIZATION_TIMEOUT_ALARM_INTERVAL_MS, NETWORK_LOGGING_TIMEOUT_ALARM_TAG,
+                mBatchTimeoutAlarmListener, this);
+        Log.d(TAG, "Scheduled a new batch finalization alarm " + BATCH_FINALIZATION_TIMEOUT_MS
                 + "ms from now.");
     }
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c3ef23b..712441c 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -100,6 +100,7 @@
 import com.android.server.statusbar.StatusBarManagerService;
 import com.android.server.storage.DeviceStorageMonitorService;
 import com.android.server.telecom.TelecomLoaderService;
+import com.android.server.text.TextClassificationService;
 import com.android.server.trust.TrustManagerService;
 import com.android.server.tv.TvInputManagerService;
 import com.android.server.tv.TvRemoteService;
@@ -951,6 +952,12 @@
                 traceEnd();
             }
 
+            if (!disableNonCoreServices) {
+                traceBeginAndSlog("StartTextClassificationService");
+                mSystemServiceManager.startService(TextClassificationService.Lifecycle.class);
+                traceEnd();
+            }
+
             if (!disableNetwork) {
                 traceBeginAndSlog("StartNetworkScoreService");
                 try {
diff --git a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
index af19acb..f89fd47 100644
--- a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
+++ b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
@@ -254,12 +254,9 @@
                     mInjector.systemPropertiesSet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, "0");
 
                     // Run on the bg thread to not block the fg thread
-                    BackgroundThread.getHandler().post(new Runnable() {
-                        @Override
-                        public void run() {
-                            if (!deletePreloadsFolderContents()) {
-                                Slog.w(TAG, "Failed to delete preloads folder contents");
-                            }
+                    BackgroundThread.getHandler().post(() -> {
+                        if (!deletePreloadsFolderContents()) {
+                            Slog.w(TAG, "Failed to delete preloads folder contents");
                         }
                     });
 
@@ -443,8 +440,29 @@
 
     private boolean deletePreloadsFolderContents() {
         final File dir = mInjector.getDataPreloadsDirectory();
+        final File[] files = FileUtils.listFilesOrEmpty(dir);
+        final File fileCacheDirectory = mInjector.getDataPreloadsFileCacheDirectory();
         Slog.i(TAG, "Deleting contents of " + dir);
-        return FileUtils.deleteContents(dir);
+        boolean success = true;
+        for (File file : files) {
+            if (file.isFile()) {
+                if (!file.delete()) {
+                    success = false;
+                    Slog.w(TAG, "Cannot delete file " + file);
+                }
+            } else {
+                // Do not remove file_cache dir
+                if (!file.equals(fileCacheDirectory)) {
+                    if (!FileUtils.deleteContentsAndDir(file)) {
+                        success = false;
+                        Slog.w(TAG, "Cannot delete dir and its content " + file);
+                    }
+                } else {
+                    Slog.i(TAG, "Skipping directory with file cache " + file);
+                }
+            }
+        }
+        return success;
     }
 
     private void registerBroadcastReceiver() {
@@ -818,6 +836,10 @@
             return Environment.getDataPreloadsDirectory();
         }
 
+        File getDataPreloadsFileCacheDirectory() {
+            return Environment.getDataPreloadsFileCacheDirectory();
+        }
+
         void publishLocalService(RetailDemoModeService service,
                 RetailDemoModeServiceInternal localService) {
             service.publishLocalService(RetailDemoModeServiceInternal.class, localService);
diff --git a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 468a26b..b865560 100644
--- a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -85,6 +85,10 @@
             300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
             300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400 };
     private static final Uri CUSTOM_SOUND = Settings.System.DEFAULT_ALARM_ALERT_URI;
+    private static final AudioAttributes CUSTOM_ATTRIBUTES = new AudioAttributes.Builder()
+            .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
+            .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
+            .build();
     private static final int CUSTOM_LIGHT_COLOR = Color.BLACK;
     private static final int CUSTOM_LIGHT_ON = 10000;
     private static final int CUSTOM_LIGHT_OFF = 10000;
@@ -200,10 +204,11 @@
         if (noisy) {
             if (defaultSound) {
                 defaults |= Notification.DEFAULT_SOUND;
-                channel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI);
+                channel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
+                        Notification.AUDIO_ATTRIBUTES_DEFAULT);
             } else {
                 builder.setSound(CUSTOM_SOUND);
-                channel.setSound(CUSTOM_SOUND);
+                channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
             }
         }
         if (buzzy) {
@@ -521,6 +526,8 @@
 
         verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), eq(FALLBACK_VIBRATION),
                 eq(-1), (AudioAttributes) anyObject());
+        verify(mRingtonePlayer, never()).playAsync
+                (anyObject(), anyObject(), anyBoolean(), anyObject());
     }
 
     @Test
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index 250aab8..e183a31 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -57,15 +57,15 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import com.android.server.lights.Light;
 import com.android.server.lights.LightsManager;
 
-@SmallTest
-@RunWith(AndroidJUnit4.class)
 public class NotificationManagerServiceTest {
+    private static final long WAIT_FOR_IDLE_TIMEOUT = 2;
     private final String pkg = "com.android.server.notification";
     private final int uid = Binder.getCallingUid();
     private NotificationManagerService mNotificationManagerService;
@@ -75,6 +75,7 @@
     private HandlerThread mThread;
 
     @Before
+    @Test
     @UiThreadTest
     public void setUp() throws Exception {
         mContext = InstrumentationRegistry.getTargetContext();
@@ -109,6 +110,9 @@
 
     public void waitForIdle() throws Exception {
         MessageQueue queue = mThread.getLooper().getQueue();
+        if (queue.isIdle()) {
+            return;
+        }
         CountDownLatch latch = new CountDownLatch(1);
         queue.addIdleHandler(new MessageQueue.IdleHandler() {
                 @Override public boolean queueIdle() {
@@ -116,10 +120,10 @@
                     return false;
                 }
         });
-        latch.await();
-        if (!queue.isIdle()) {
-            waitForIdle();
-        }
+        // Timeout is valid in the cases where the queue goes idle before the IdleHandler
+        // is added.
+        latch.await(WAIT_FOR_IDLE_TIMEOUT, TimeUnit.SECONDS);
+        waitForIdle();
     }
 
     private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
index 15dcc26..2ab1f30 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
@@ -118,6 +118,7 @@
                 defaults |= Notification.DEFAULT_SOUND;
             } else {
                 builder.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
+                channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
             }
         }
         if (buzzy) {
@@ -150,29 +151,31 @@
 
     @Test
     public void testSound_default_preUpgradeUsesNotification() throws Exception {
-        defaultChannel.setSound(null);
+        defaultChannel.setSound(null, null);
         // pre upgrade, default sound.
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, record.getSound());
+        assertEquals(Notification.AUDIO_ATTRIBUTES_DEFAULT, record.getAudioAttributes());
     }
 
     @Test
     public void testSound_custom_preUpgradeUsesNotification() throws Exception {
-        defaultChannel.setSound(null);
+        defaultChannel.setSound(null, null);
         // pre upgrade, custom sound.
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(CUSTOM_SOUND, record.getSound());
+        assertEquals(CUSTOM_ATTRIBUTES, record.getAudioAttributes());
     }
 
     @Test
     public void testSound_default_userLocked_preUpgrade() throws Exception {
-        defaultChannel.setSound(CUSTOM_SOUND);
+        defaultChannel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
         defaultChannel.lockFields(NotificationChannel.USER_LOCKED_SOUND);
         // pre upgrade, default sound.
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
@@ -180,17 +183,19 @@
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(CUSTOM_SOUND, record.getSound());
+        assertEquals(CUSTOM_ATTRIBUTES, record.getAudioAttributes());
     }
 
     @Test
     public void testSound_default_upgradeUsesChannel() throws Exception {
-        channel.setSound(CUSTOM_SOUND);
+        channel.setSound(CUSTOM_SOUND, CUSTOM_ATTRIBUTES);
         // post upgrade, default sound.
         StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
         assertEquals(CUSTOM_SOUND, record.getSound());
+        assertEquals(CUSTOM_ATTRIBUTES, record.getAudioAttributes());
     }
 
     @Test
@@ -239,28 +244,6 @@
     }
 
     @Test
-    public void testAudioAttributes_preUpgrade() throws Exception {
-        defaultChannel.setSound(null);
-        // pre upgrade, default sound.
-        StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
-                false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */);
-
-        NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
-        assertEquals(CUSTOM_ATTRIBUTES, record.getAudioAttributes());
-    }
-
-    @Test
-    public void testAudioAttributes_upgrade() throws Exception {
-        channel.setSound(null);
-        // post upgrade, default sound.
-        StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
-                false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */);
-
-        NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
-        assertEquals(CUSTOM_ATTRIBUTES, record.getAudioAttributes());
-    }
-
-    @Test
     public void testImportance_preUpgrade() throws Exception {
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */);
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index 0320d8a..9fa46d1 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -30,12 +30,13 @@
 import org.xmlpull.v1.XmlSerializer;
 
 import android.app.Notification;
+import android.app.NotificationChannelGroup;
 import android.content.Context;
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.ParceledListSlice;
+import android.media.AudioAttributes;
 import android.net.Uri;
 import android.os.Build;
 import android.os.UserHandle;
@@ -66,9 +67,12 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class RankingHelperTest {
-    @Mock NotificationUsageStats mUsageStats;
-    @Mock RankingHandler handler;
-    @Mock PackageManager mPm;
+    @Mock
+    NotificationUsageStats mUsageStats;
+    @Mock
+    RankingHandler handler;
+    @Mock
+    PackageManager mPm;
 
     private Notification mNotiGroupGSortA;
     private Notification mNotiGroupGSortB;
@@ -85,6 +89,7 @@
     private final int uid = 0;
     private final String pkg2 = "pkg2";
     private final int uid2 = 1111111;
+    private AudioAttributes mAudioAttributes;
 
     private Context getContext() {
         return InstrumentationRegistry.getTargetContext();
@@ -96,7 +101,7 @@
         UserHandle user = UserHandle.ALL;
 
         mHelper = new RankingHelper(getContext(), mPm, handler, mUsageStats,
-                new String[] {ImportanceExtractor.class.getName()});
+                new String[]{ImportanceExtractor.class.getName()});
 
         mNotiGroupGSortA = new Notification.Builder(getContext())
                 .setContentTitle("A")
@@ -143,6 +148,12 @@
                 "package", "package", 1, null, 0, 0, mNotiNoGroupSortA, user,
                 null, System.currentTimeMillis()), getDefaultChannel());
 
+        mAudioAttributes = new AudioAttributes.Builder()
+                .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
+                .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
+                .setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED)
+                .build();
+
         final ApplicationInfo legacy = new ApplicationInfo();
         legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
         final ApplicationInfo upgrade = new ApplicationInfo();
@@ -150,7 +161,8 @@
         try {
             when(mPm.getApplicationInfoAsUser(eq(pkg), anyInt(), anyInt())).thenReturn(legacy);
             when(mPm.getApplicationInfoAsUser(eq(pkg2), anyInt(), anyInt())).thenReturn(upgrade);
-        } catch (PackageManager.NameNotFoundException e) {}
+        } catch (PackageManager.NameNotFoundException e) {
+        }
     }
 
     private NotificationChannel getDefaultChannel() {
@@ -186,6 +198,8 @@
         assertEquals(expected.getSound(), actual.getSound());
         assertEquals(expected.canBypassDnd(), actual.canBypassDnd());
         assertTrue(Arrays.equals(expected.getVibrationPattern(), actual.getVibrationPattern()));
+        assertEquals(expected.getGroup(), actual.getGroup());
+        assertEquals(expected.getAudioAttributes(), actual.getAudioAttributes());
     }
 
     @Test
@@ -240,17 +254,20 @@
 
     @Test
     public void testChannelXml() throws Exception {
+        NotificationChannelGroup ncg = new NotificationChannelGroup("1", "2");
         NotificationChannel channel1 =
                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
         NotificationChannel channel2 =
                 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
-        channel2.setSound(new Uri.Builder().scheme("test").build());
+        channel2.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
         channel2.setLights(true);
         channel2.setBypassDnd(true);
         channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
         channel2.enableVibration(true);
-        channel2.setVibrationPattern(new long[] {100, 67, 145, 156});
+        channel2.setGroup(ncg.getId());
+        channel2.setVibrationPattern(new long[]{100, 67, 145, 156});
 
+        mHelper.createNotificationChannelGroup(pkg, uid, ncg, true);
         mHelper.createNotificationChannel(pkg, uid, channel1, true);
         mHelper.createNotificationChannel(pkg, uid, channel2, false);
 
@@ -274,6 +291,10 @@
                 mHelper.getNotificationChannel(pkg, uid, channel2.getId(), false));
         assertNotNull(mHelper.getNotificationChannel(
                 pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false));
+        assertEquals(ncg.getId(),
+                mHelper.getNotificationChannelGroups(pkg, uid, false).getList().get(0).getId());
+        assertEquals(channel2.getGroup(), mHelper.getNotificationChannelGroups(
+                pkg, uid, false).getList().get(0).getChannels().get(0).getGroup());
     }
 
     @Test
@@ -296,13 +317,13 @@
                 pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID, false);
         assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, updated.getImportance());
         assertFalse(updated.canBypassDnd());
-        assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE,updated.getLockscreenVisibility());
+        assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, updated.getLockscreenVisibility());
         assertEquals(0, updated.getUserLockedFields());
     }
 
     @Test
     public void testChannelXml_defaultChannelUpdatedApp_userSettings() throws Exception {
-         NotificationChannel channel1 =
+        NotificationChannel channel1 =
                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_MIN);
         mHelper.createNotificationChannel(pkg, uid, channel1, true);
 
@@ -327,15 +348,16 @@
     @Test
     public void testChannelXml_upgradeCreateDefaultChannel() throws Exception {
         final String preupgradeXml = "<ranking version=\"1\">\n"
-             + "<package name=\"" + pkg + "\" importance=\"" + NotificationManager.IMPORTANCE_HIGH
-            + "\" priority=\"" + Notification.PRIORITY_MAX + "\" visibility=\""
-            + Notification.VISIBILITY_SECRET + "\"" +" uid=\"" + uid + "\" />\n"
-            + "<package name=\"" + pkg2 + "\" uid=\"" + uid2 + "\" visibility=\""
-            + Notification.VISIBILITY_PRIVATE + "\" />\n"
-            + "</ranking>";
+                + "<package name=\"" + pkg + "\" importance=\""
+                + NotificationManager.IMPORTANCE_HIGH
+                + "\" priority=\"" + Notification.PRIORITY_MAX + "\" visibility=\""
+                + Notification.VISIBILITY_SECRET + "\"" + " uid=\"" + uid + "\" />\n"
+                + "<package name=\"" + pkg2 + "\" uid=\"" + uid2 + "\" visibility=\""
+                + Notification.VISIBILITY_PRIVATE + "\" />\n"
+                + "</ranking>";
         XmlPullParser parser = Xml.newPullParser();
         parser.setInput(new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
-            null);
+                null);
         parser.nextTag();
         mHelper.readXml(parser, false);
 
@@ -345,8 +367,8 @@
         assertTrue(updated1.canBypassDnd());
         assertEquals(Notification.VISIBILITY_SECRET, updated1.getLockscreenVisibility());
         assertEquals(NotificationChannel.USER_LOCKED_IMPORTANCE
-            | NotificationChannel.USER_LOCKED_PRIORITY
-            | NotificationChannel.USER_LOCKED_VISIBILITY, updated1.getUserLockedFields());
+                | NotificationChannel.USER_LOCKED_PRIORITY
+                | NotificationChannel.USER_LOCKED_VISIBILITY, updated1.getUserLockedFields());
 
         final NotificationChannel updated2 = mHelper.getNotificationChannel(
                 pkg2, uid2, NotificationChannel.DEFAULT_CHANNEL_ID, false);
@@ -374,14 +396,14 @@
     public void testUpdate_userLockedImportance() throws Exception {
         // all fields locked by user
         final NotificationChannel channel =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
         channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
 
         mHelper.createNotificationChannel(pkg, uid, channel, false);
 
         // same id, try to update
         final NotificationChannel channel2 =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
 
         mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
 
@@ -393,7 +415,7 @@
     public void testUpdate_userLockedVisibility() throws Exception {
         // all fields locked by user
         final NotificationChannel channel =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
         channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
         channel.lockFields(NotificationChannel.USER_LOCKED_VISIBILITY);
 
@@ -401,7 +423,7 @@
 
         // same id, try to update
         final NotificationChannel channel2 =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
         channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
 
         mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
@@ -414,7 +436,7 @@
     public void testUpdate_userLockedVibration() throws Exception {
         // all fields locked by user
         final NotificationChannel channel =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
         channel.setLights(false);
         channel.lockFields(NotificationChannel.USER_LOCKED_VIBRATION);
 
@@ -422,9 +444,9 @@
 
         // same id, try to update
         final NotificationChannel channel2 =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
         channel2.enableVibration(true);
-        channel2.setVibrationPattern(new long[] {100});
+        channel2.setVibrationPattern(new long[]{100});
 
         mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
 
@@ -436,7 +458,7 @@
     public void testUpdate_userLockedLights() throws Exception {
         // all fields locked by user
         final NotificationChannel channel =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
         channel.setLights(false);
         channel.lockFields(NotificationChannel.USER_LOCKED_LIGHTS);
 
@@ -444,7 +466,7 @@
 
         // same id, try to update
         final NotificationChannel channel2 =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
         channel2.setLights(true);
 
         mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
@@ -457,7 +479,7 @@
     public void testUpdate_userLockedPriority() throws Exception {
         // all fields locked by user
         final NotificationChannel channel =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
         channel.setBypassDnd(true);
         channel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY);
 
@@ -465,7 +487,7 @@
 
         // same id, try to update all fields
         final NotificationChannel channel2 =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
         channel2.setBypassDnd(false);
 
         mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
@@ -478,16 +500,16 @@
     public void testUpdate_userLockedRingtone() throws Exception {
         // all fields locked by user
         final NotificationChannel channel =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
-        channel.setSound(new Uri.Builder().scheme("test").build());
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
         channel.lockFields(NotificationChannel.USER_LOCKED_SOUND);
 
         mHelper.createNotificationChannel(pkg, uid, channel, false);
 
         // same id, try to update all fields
         final NotificationChannel channel2 =
-            new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
-        channel2.setSound(new Uri.Builder().scheme("test2").build());
+                new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+        channel2.setSound(new Uri.Builder().scheme("test2").build(), mAudioAttributes);
 
         mHelper.updateNotificationChannelFromAssistant(pkg, uid, channel2);
 
@@ -519,7 +541,7 @@
         // no fields locked by user
         final NotificationChannel channel =
                 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
-        channel.setSound(new Uri.Builder().scheme("test").build());
+        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
         channel.setLights(true);
         channel.setBypassDnd(true);
         channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
@@ -529,7 +551,7 @@
         // same id, try to update all fields
         final NotificationChannel channel2 =
                 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
-        channel2.setSound(new Uri.Builder().scheme("test2").build());
+        channel2.setSound(new Uri.Builder().scheme("test2").build(), mAudioAttributes);
         channel2.setLights(false);
         channel2.setBypassDnd(false);
         channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
@@ -551,7 +573,7 @@
     public void testCreateChannel_CannotChangeHiddenFields() throws Exception {
         final NotificationChannel channel =
                 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
-        channel.setSound(new Uri.Builder().scheme("test").build());
+        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
         channel.setLights(true);
         channel.setBypassDnd(true);
         channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
@@ -578,7 +600,7 @@
     public void testCreateChannel_CannotChangeHiddenFieldsAssistant() throws Exception {
         final NotificationChannel channel =
                 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
-        channel.setSound(new Uri.Builder().scheme("test").build());
+        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
         channel.setLights(true);
         channel.setBypassDnd(true);
         channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
@@ -605,12 +627,12 @@
     public void testGetDeletedChannel() throws Exception {
         NotificationChannel channel =
                 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
-        channel.setSound(new Uri.Builder().scheme("test").build());
+        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
         channel.setLights(true);
         channel.setBypassDnd(true);
         channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
         channel.enableVibration(true);
-        channel.setVibrationPattern(new long[] {100, 67, 145, 156});
+        channel.setVibrationPattern(new long[]{100, 67, 145, 156});
 
         mHelper.createNotificationChannel(pkg, uid, channel, true);
         mHelper.deleteNotificationChannel(pkg, uid, channel.getId());
@@ -631,12 +653,12 @@
         Map<String, NotificationChannel> channelMap = new HashMap<>();
         NotificationChannel channel =
                 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
-        channel.setSound(new Uri.Builder().scheme("test").build());
+        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
         channel.setLights(true);
         channel.setBypassDnd(true);
         channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
         channel.enableVibration(true);
-        channel.setVibrationPattern(new long[] {100, 67, 145, 156});
+        channel.setVibrationPattern(new long[]{100, 67, 145, 156});
         channelMap.put(channel.getId(), channel);
         NotificationChannel channel2 =
                 new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH);
@@ -657,7 +679,7 @@
         }
 
         // Returns deleted channels too
-        channels =  mHelper.getNotificationChannels(pkg, uid, true).getList();
+        channels = mHelper.getNotificationChannels(pkg, uid, true).getList();
         assertEquals(3, channels.size());               // Includes default channel
         for (NotificationChannel nc : channels) {
             if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) {
@@ -674,7 +696,7 @@
 
         mHelper.deleteNotificationChannel(pkg, uid, channel.getId());
 
-        channel.setSound(new Uri.Builder().scheme("test").build());
+        channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
         try {
             mHelper.updateNotificationChannel(pkg, uid, channel);
             fail("Updated deleted channel");
@@ -692,7 +714,7 @@
 
     @Test
     public void testCreateDeletedChannel() throws Exception {
-        long[] vibration = new long[] {100, 67, 145, 156};
+        long[] vibration = new long[]{100, 67, 145, 156};
         NotificationChannel channel =
                 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
         channel.setVibrationPattern(vibration);
@@ -702,7 +724,7 @@
 
         NotificationChannel newChannel = new NotificationChannel(
                 channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH);
-        newChannel.setVibrationPattern(new long[] {100});
+        newChannel.setVibrationPattern(new long[]{100});
 
         mHelper.createNotificationChannel(pkg, uid, newChannel, true);
 
@@ -713,7 +735,7 @@
 
     @Test
     public void testCreateChannel_alreadyExists() throws Exception {
-        long[] vibration = new long[] {100, 67, 145, 156};
+        long[] vibration = new long[]{100, 67, 145, 156};
         NotificationChannel channel =
                 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
         channel.setVibrationPattern(vibration);
@@ -722,7 +744,7 @@
 
         NotificationChannel newChannel = new NotificationChannel(
                 channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH);
-        newChannel.setVibrationPattern(new long[] {100});
+        newChannel.setVibrationPattern(new long[]{100});
 
         mHelper.createNotificationChannel(pkg, uid, newChannel, true);
 
@@ -766,9 +788,113 @@
     }
 
     @Test
+    public void testOnPackageChanged_packageRemoval_importance() throws Exception {
+        mHelper.setImportance(pkg, uid, NotificationManager.IMPORTANCE_HIGH);
+
+        mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{pkg}, new int[]{uid});
+
+        assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(pkg, uid));
+    }
+
+    @Test
+    public void testOnPackageChanged_packageRemoval_groups() throws Exception {
+        NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+        mHelper.createNotificationChannelGroup(pkg, uid, ncg, true);
+        NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2");
+        mHelper.createNotificationChannelGroup(pkg, uid, ncg2, true);
+
+        mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{pkg}, new int[]{uid});
+
+        assertEquals(0, mHelper.getNotificationChannelGroups(pkg, uid, true).getList().size());
+    }
+
+    @Test
     public void testRecordDefaults() throws Exception {
         assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(pkg, uid));
         assertEquals(true, mHelper.canShowBadge(pkg, uid));
         assertEquals(1, mHelper.getNotificationChannels(pkg, uid, false).getList().size());
     }
+
+    @Test
+    public void testCreateGroup() throws Exception {
+        NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+        mHelper.createNotificationChannelGroup(pkg, uid, ncg, true);
+        assertEquals(ncg, mHelper.getNotificationChannelGroups(pkg, uid).iterator().next());
+    }
+
+    @Test
+    public void testCannotCreateChannel_badGroup() throws Exception {
+        NotificationChannel channel1 =
+                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+        channel1.setGroup("garbage");
+        try {
+            mHelper.createNotificationChannel(pkg, uid, channel1, true);
+            fail("Created a channel with a bad group");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
+    @Test
+    public void testCannotCreateChannel_goodGroup() throws Exception {
+        NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+        mHelper.createNotificationChannelGroup(pkg, uid, ncg, true);
+        NotificationChannel channel1 =
+                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+        channel1.setGroup(ncg.getId());
+        mHelper.createNotificationChannel(pkg, uid, channel1, true);
+
+        assertEquals(ncg.getId(),
+                mHelper.getNotificationChannel(pkg, uid, channel1.getId(), false).getGroup());
+    }
+
+    @Test
+    public void testGetChannelGroups() throws Exception {
+        NotificationChannelGroup unused = new NotificationChannelGroup("unused", "s");
+        mHelper.createNotificationChannelGroup(pkg, uid, unused, true);
+        NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+        mHelper.createNotificationChannelGroup(pkg, uid, ncg, true);
+        NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2");
+        mHelper.createNotificationChannelGroup(pkg, uid, ncg2, true);
+
+        NotificationChannel channel1 =
+                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+        channel1.setGroup(ncg.getId());
+        mHelper.createNotificationChannel(pkg, uid, channel1, true);
+        NotificationChannel channel1a =
+                new NotificationChannel("id1a", "name1", NotificationManager.IMPORTANCE_HIGH);
+        channel1a.setGroup(ncg.getId());
+        mHelper.createNotificationChannel(pkg, uid, channel1a, true);
+
+        NotificationChannel channel2 =
+                new NotificationChannel("id2", "name1", NotificationManager.IMPORTANCE_HIGH);
+        channel2.setGroup(ncg2.getId());
+        mHelper.createNotificationChannel(pkg, uid, channel2, true);
+
+        NotificationChannel channel3 =
+                new NotificationChannel("id3", "name1", NotificationManager.IMPORTANCE_HIGH);
+        mHelper.createNotificationChannel(pkg, uid, channel3, true);
+
+        List<NotificationChannelGroup> actual =
+                mHelper.getNotificationChannelGroups(pkg, uid, true).getList();
+        assertEquals(3, actual.size());
+        for (NotificationChannelGroup group : actual) {
+            if (group.getId() == null) {
+                assertEquals(2, group.getChannels().size()); // misc channel too
+                assertTrue(channel3.getId().equals(group.getChannels().get(0).getId())
+                        || channel3.getId().equals(group.getChannels().get(1).getId()));
+            } else if (group.getId().equals(ncg.getId())) {
+                assertEquals(2, group.getChannels().size());
+                if (group.getChannels().get(0).getId().equals(channel1.getId())) {
+                    assertTrue(group.getChannels().get(1).getId().equals(channel1a.getId()));
+                } else if (group.getChannels().get(0).getId().equals(channel1a.getId())) {
+                    assertTrue(group.getChannels().get(1).getId().equals(channel1.getId()));
+                } else {
+                    fail("expected channel not found");
+                }
+            } else if (group.getId().equals(ncg2.getId())) {
+                assertEquals(1, group.getChannels().size());
+                assertEquals(channel2.getId(), group.getChannels().get(0).getId());
+            }
+        }
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index 4ca29cd..152b9c9 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -106,7 +106,7 @@
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
-import java.util.function.Function;
+import java.util.function.UnaryOperator;
 
 /**
  * Tests for {@link NetworkScoreService}.
@@ -132,8 +132,8 @@
     @Mock private INetworkScoreCache.Stub mNetworkScoreCache, mNetworkScoreCache2;
     @Mock private IBinder mIBinder, mIBinder2;
     @Mock private INetworkRecommendationProvider mRecommendationProvider;
-    @Mock private Function<List<ScoredNetwork>, List<ScoredNetwork>> mCurrentNetworkFilter;
-    @Mock private Function<List<ScoredNetwork>, List<ScoredNetwork>> mScanResultsFilter;
+    @Mock private UnaryOperator<List<ScoredNetwork>> mCurrentNetworkFilter;
+    @Mock private UnaryOperator<List<ScoredNetwork>> mScanResultsFilter;
     @Mock private WifiInfo mWifiInfo;
     @Captor private ArgumentCaptor<List<ScoredNetwork>> mScoredNetworkCaptor;
 
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index 969cb36..213fb27 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -1263,25 +1263,6 @@
     }
 
     @SmallTest
-    public void testHasFeaturesReadAccountsNotPermitted() throws Exception {
-        unlockSystemUser();
-        when(mMockContext.checkCallingOrSelfPermission(anyString())).thenReturn(
-                PackageManager.PERMISSION_DENIED);
-        when(mMockPackageManager.checkSignatures(anyInt(), anyInt()))
-                    .thenReturn(PackageManager.SIGNATURE_NO_MATCH);
-        try {
-            mAms.hasFeatures(
-                mMockAccountManagerResponse, // response
-                AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, // account
-                new String[] {"feature1", "feature2"}, // features
-                "testPackage"); // opPackageName
-            fail("SecurityException expected. But no exception was thrown.");
-        } catch (SecurityException e) {
-            // SecurityException is expected.
-        }
-    }
-
-    @SmallTest
     public void testHasFeaturesReturnNullResult() throws Exception {
         unlockSystemUser();
         final CountDownLatch latch = new CountDownLatch(1);
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
index 8591dae..2e045ff 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
@@ -374,7 +374,7 @@
         mAccountsDb.setAccountVisibility(accId, uid2, 3);
         assertEquals(mAccountsDb.findAccountVisibility(accId, uid2), Integer.valueOf(3));
 
-        Map<Integer, Integer> vis = mAccountsDb.findAccountVisibilityForAccountId(accId);
+        Map<Integer, Integer> vis = mAccountsDb.findAllVisibilityValuesForAccount(account);
         assertEquals(vis.size(), 2);
         assertEquals(vis.get(uid1), Integer.valueOf(1));
         assertEquals(vis.get(uid2), Integer.valueOf(3));
diff --git a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
index 677e468..d7bfc44 100644
--- a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
@@ -36,6 +36,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.IntentSender;
+import android.content.pm.LauncherApps;
 import android.content.pm.ShortcutServiceInternal;
 import android.os.Handler;
 import android.os.UserHandle;
@@ -121,6 +122,18 @@
         assertEquals(provider, providerCaptor.getValue().provider);
     }
 
+    public void testIsRequestPinAppWidgetSupported() {
+        ComponentName provider = new ComponentName(mTestContext, DummyAppWidget.class);
+        // Set up users.
+        when(mMockShortcutService.isRequestPinItemSupported(anyInt(), anyInt()))
+                .thenReturn(true, false);
+        assertTrue(mManager.isRequestPinAppWidgetSupported());
+        assertFalse(mManager.isRequestPinAppWidgetSupported());
+
+        verify(mMockShortcutService, times(2)).isRequestPinItemSupported(anyInt(),
+                eq(LauncherApps.PinItemRequest.REQUEST_TYPE_APPWIDGET));
+    }
+
     public void testProviderUpdatesReceived() throws Exception {
         int widgetId = setupHostAndWidget();
         RemoteViews view = new RemoteViews(mPkgName, android.R.layout.simple_list_item_1);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 5d4c3cf..f4e4e08 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -1950,6 +1950,81 @@
         }
     }
 
+    public void testCreateAdminSupportIntent() throws Exception {
+        // Setup device owner.
+        mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+        setupDeviceOwner();
+
+        // Nonexisting permission returns null
+        Intent intent = dpm.createAdminSupportIntent("disallow_nothing");
+        assertNull(intent);
+
+        // Existing permission that is not set returns null
+        intent = dpm.createAdminSupportIntent(UserManager.DISALLOW_ADJUST_VOLUME);
+        assertNull(intent);
+
+        // Existing permission that is not set by device/profile owner returns null
+        when(mContext.userManager.hasUserRestriction(
+                eq(UserManager.DISALLOW_ADJUST_VOLUME),
+                eq(UserHandle.getUserHandleForUid(mContext.binder.callingUid))))
+                .thenReturn(true);
+        intent = dpm.createAdminSupportIntent(UserManager.DISALLOW_ADJUST_VOLUME);
+        assertNull(intent);
+
+        // Permission that is set by device owner returns correct intent
+        when(mContext.userManager.getUserRestrictionSource(
+                eq(UserManager.DISALLOW_ADJUST_VOLUME),
+                eq(UserHandle.getUserHandleForUid(mContext.binder.callingUid))))
+                .thenReturn(UserManager.RESTRICTION_SOURCE_DEVICE_OWNER);
+        intent = dpm.createAdminSupportIntent(UserManager.DISALLOW_ADJUST_VOLUME);
+        assertNotNull(intent);
+        assertEquals(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS, intent.getAction());
+        assertEquals(UserHandle.getUserId(DpmMockContext.CALLER_SYSTEM_USER_UID),
+                intent.getIntExtra(Intent.EXTRA_USER_ID, -1));
+        assertEquals(admin1,
+                (ComponentName) intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN));
+        assertEquals(UserManager.DISALLOW_ADJUST_VOLUME,
+                intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION));
+
+        // Try with POLICY_DISABLE_CAMERA and POLICY_DISABLE_SCREEN_CAPTURE, which are not
+        // user restrictions
+
+        // Camera is not disabled
+        intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_CAMERA);
+        assertNull(intent);
+
+        // Camera is disabled
+        dpm.setCameraDisabled(admin1, true);
+        intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_CAMERA);
+        assertNotNull(intent);
+        assertEquals(DevicePolicyManager.POLICY_DISABLE_CAMERA,
+                intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION));
+
+        // Screen capture is not disabled
+        intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE);
+        assertNull(intent);
+
+        // Screen capture is disabled
+        dpm.setScreenCaptureDisabled(admin1, true);
+        intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE);
+        assertNotNull(intent);
+        assertEquals(DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE,
+                intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION));
+
+        // Same checks for different user
+        mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+        // Camera should be disabled by device owner
+        intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_CAMERA);
+        assertNotNull(intent);
+        assertEquals(DevicePolicyManager.POLICY_DISABLE_CAMERA,
+                intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION));
+        assertEquals(UserHandle.getUserId(DpmMockContext.CALLER_SYSTEM_USER_UID),
+                intent.getIntExtra(Intent.EXTRA_USER_ID, -1));
+        // ScreenCapture should not be disabled by device owner
+        intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE);
+        assertNull(intent);
+    }
+
     /**
      * Test for:
      * {@link DevicePolicyManager#setAffiliationIds}
@@ -3500,20 +3575,24 @@
 
         // System can retrieve permission grant state.
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
+        mContext.packageName = "com.example.system";
         assertEquals(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED,
                 dpm.getPermissionGrantState(null, app1, permission));
         assertEquals(DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT,
                 dpm.getPermissionGrantState(null, app2, permission));
 
         // A regular app cannot retrieve permission grant state.
-        mMockContext.binder.callingUid = DpmMockContext.CALLER_UID;
+        mContext.binder.callingUid = setupPackageInPackageManager(app1, 1);
+        mContext.packageName = app1;
         try {
             dpm.getPermissionGrantState(null, app1, permission);
-            fail("Didn't throw IllegalStateException");
-        } catch (IllegalStateException expected) {
+            fail("Didn't throw SecurityException");
+        } catch (SecurityException expected) {
         }
 
         // Profile owner can retrieve permission grant state.
+        mContext.binder.callingUid = DpmMockContext.CALLER_UID;
+        mContext.packageName = admin1.getPackageName();
         setAsProfileOwner(admin1);
         assertEquals(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED,
                 dpm.getPermissionGrantState(admin1, app1, permission));
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 9835c88..8c23a91 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -398,7 +398,7 @@
 
         @Override
         ComponentName injectGetPinConfirmationActivity(@NonNull String launcherPackageName,
-                int launcherUserId) {
+                int launcherUserId, int requestType) {
             return mPinConfirmActivityFetcher.apply(launcherPackageName, launcherUserId);
         }
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
index 96e8948..0310e16 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
@@ -93,21 +93,24 @@
 
         Pair<ComponentName, Integer> actual;
         // User 0
-        actual = mProcessor.getRequestPinShortcutConfirmationActivity(USER_0);
+        actual = mProcessor.getRequestPinConfirmationActivity(USER_0,
+                PinItemRequest.REQUEST_TYPE_SHORTCUT);
 
         assertEquals(LAUNCHER_1, actual.first.getPackageName());
         assertEquals(PIN_CONFIRM_ACTIVITY_CLASS, actual.first.getClassName());
         assertEquals(USER_0, (int) actual.second);
 
         // User 10
-        actual = mProcessor.getRequestPinShortcutConfirmationActivity(USER_10);
+        actual = mProcessor.getRequestPinConfirmationActivity(USER_10,
+                PinItemRequest.REQUEST_TYPE_SHORTCUT);
 
         assertEquals(LAUNCHER_2, actual.first.getPackageName());
         assertEquals(PIN_CONFIRM_ACTIVITY_CLASS, actual.first.getClassName());
         assertEquals(USER_10, (int) actual.second);
 
         // User P0 -> managed profile, return user-0's launcher.
-        actual = mProcessor.getRequestPinShortcutConfirmationActivity(USER_P0);
+        actual = mProcessor.getRequestPinConfirmationActivity(USER_P0,
+                PinItemRequest.REQUEST_TYPE_SHORTCUT);
 
         assertEquals(LAUNCHER_1, actual.first.getPackageName());
         assertEquals(PIN_CONFIRM_ACTIVITY_CLASS, actual.first.getClassName());
@@ -133,15 +136,18 @@
                         ? null : new ComponentName(packageName, PIN_CONFIRM_ACTIVITY_CLASS);
 
         // User 10 -- still has confirm activity.
-        actual = mProcessor.getRequestPinShortcutConfirmationActivity(USER_10);
+        actual = mProcessor.getRequestPinConfirmationActivity(USER_10,
+                PinItemRequest.REQUEST_TYPE_SHORTCUT);
 
         assertEquals(LAUNCHER_2, actual.first.getPackageName());
         assertEquals(PIN_CONFIRM_ACTIVITY_CLASS, actual.first.getClassName());
         assertEquals(USER_10, (int) actual.second);
 
         // But user-0 and user p0 no longer has a confirmation activity.
-        assertNull(mProcessor.getRequestPinShortcutConfirmationActivity(USER_0));
-        assertNull(mProcessor.getRequestPinShortcutConfirmationActivity(USER_P0));
+        assertNull(mProcessor.getRequestPinConfirmationActivity(USER_0,
+                PinItemRequest.REQUEST_TYPE_SHORTCUT));
+        assertNull(mProcessor.getRequestPinConfirmationActivity(USER_P0,
+                PinItemRequest.REQUEST_TYPE_SHORTCUT));
 
         // Check from the public API.
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
@@ -204,7 +210,7 @@
     }
 
     private void assertPinItemRequestIntent(Intent actualIntent, String expectedPackage) {
-        assertEquals(LauncherApps.ACTION_CONFIRM_PIN_ITEM, actualIntent.getAction());
+        assertEquals(LauncherApps.ACTION_CONFIRM_PIN_SHORTCUT, actualIntent.getAction());
         assertEquals(expectedPackage, actualIntent.getComponent().getPackageName());
         assertEquals(PIN_CONFIRM_ACTIVITY_CLASS,
                 actualIntent.getComponent().getClassName());
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
index cfa35c2..26033a3 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
@@ -72,7 +72,7 @@
     }
 
     private void assertPinItemRequestIntent(Intent actualIntent, String expectedPackage) {
-        assertEquals(LauncherApps.ACTION_CONFIRM_PIN_ITEM, actualIntent.getAction());
+        assertEquals(LauncherApps.ACTION_CONFIRM_PIN_APPWIDGET, actualIntent.getAction());
         assertEquals(expectedPackage, actualIntent.getComponent().getPackageName());
         assertEquals(PIN_CONFIRM_ACTIVITY_CLASS,
                 actualIntent.getComponent().getClassName());
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 9b2c94e..1964cad 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -177,10 +177,12 @@
         UserInfo userInfo = createProfileForUser("Profile",
                 UserInfo.FLAG_MANAGED_PROFILE, primaryUserId);
         assertNotNull(userInfo);
-
+        assertNull(mUserManager.getProfileParent(primaryUserId));
         UserInfo parentProfileInfo = mUserManager.getProfileParent(userInfo.id);
         assertNotNull(parentProfileInfo);
         assertEquals(parentProfileInfo.id, primaryUserId);
+        removeUser(userInfo.id);
+        assertNull(mUserManager.getProfileParent(primaryUserId));
     }
 
     // Make sure only one managed profile can be created
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
index 0361cb5..4d76312 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
@@ -203,6 +203,46 @@
         assertNull(getPackageUseInfo(mBarUser1));
     }
 
+    @Test
+    public void testNotifyPackageInstallUsedByOther() {
+        TestData newPackage = new TestData("newPackage",
+                VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]), mUser0);
+
+        List<String> newSecondaries = newPackage.getSecondaryDexPaths();
+        // Before we notify about the installation of the newPackage if mFoo
+        // is trying to load something from it we should not find it.
+        notifyDexLoad(mFooUser0, newSecondaries, mUser0);
+        assertNull(getPackageUseInfo(newPackage));
+
+        // Notify about newPackage install and let mFoo load its dexes.
+        mDexManager.notifyPackageInstalled(newPackage.mPackageInfo, mUser0);
+        notifyDexLoad(mFooUser0, newSecondaries, mUser0);
+
+        // We should get back the right info.
+        PackageUseInfo pui = getPackageUseInfo(newPackage);
+        assertNotNull(pui);
+        assertFalse(pui.isUsedByOtherApps());
+        assertEquals(newSecondaries.size(), pui.getDexUseInfoMap().size());
+        assertSecondaryUse(newPackage, pui, newSecondaries, /*isUsedByOtherApps*/true, mUser0);
+    }
+
+    @Test
+    public void testNotifyPackageInstallSelfUse() {
+        TestData newPackage = new TestData("newPackage",
+                VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]), mUser0);
+
+        List<String> newSecondaries = newPackage.getSecondaryDexPaths();
+        // Packages should be able to find their own dex files even if the notification about
+        // their installation is delayed.
+        notifyDexLoad(newPackage, newSecondaries, mUser0);
+
+        PackageUseInfo pui = getPackageUseInfo(newPackage);
+        assertNotNull(pui);
+        assertFalse(pui.isUsedByOtherApps());
+        assertEquals(newSecondaries.size(), pui.getDexUseInfoMap().size());
+        assertSecondaryUse(newPackage, pui, newSecondaries, /*isUsedByOtherApps*/false, mUser0);
+    }
+
     private void assertSecondaryUse(TestData testData, PackageUseInfo pui,
             List<String> secondaries, boolean isUsedByOtherApps, int ownerUserId) {
         for (String dex : secondaries) {
diff --git a/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java b/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
index d53fdf6..e1dda51 100644
--- a/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
@@ -449,6 +449,11 @@
         }
 
         @Override
+        File getDataPreloadsFileCacheDirectory() {
+            return new File(mTestPreloadsDir, "file_cache");
+        }
+
+        @Override
         void publishLocalService(RetailDemoModeService service,
                 RetailDemoModeServiceInternal localService) {
         }
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
index 2af4163..04e5583 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
@@ -29,6 +29,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
 
 /**
  * Test class for {@link AppWindowContainerController}.
@@ -135,9 +136,50 @@
         assertHasStartingWindow(controller2.getAppWindowToken());
     }
 
+    @Test
+    public void testReparent() throws Exception {
+        final TestTaskWindowContainerController taskController1 =
+                new TestTaskWindowContainerController(
+                        createStackControllerOnDisplay(sDisplayContent));
+        final TestAppWindowContainerController appWindowController1 = createAppWindowController(
+                taskController1);
+        final TestTaskWindowContainerController taskController2 =
+                new TestTaskWindowContainerController(
+                        createStackControllerOnDisplay(sDisplayContent));
+        final TestAppWindowContainerController appWindowController2 = createAppWindowController(
+                taskController2);
+        final TestTaskWindowContainerController taskController3 =
+                new TestTaskWindowContainerController(
+                        createStackControllerOnDisplay(sDisplayContent));
+
+        try {
+            appWindowController1.reparent(taskController1, 0);
+            fail("Should not be able to reparent to the same parent");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+
+        try {
+            taskController3.setContainer(null);
+            appWindowController1.reparent(taskController3, 0);
+            fail("Should not be able to reparent to a task that doesn't have a container");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+
+        // Reparent the app window and ensure that it is moved
+        appWindowController1.reparent(taskController2, 0);
+        assertEquals(taskController2.mContainer, appWindowController1.mContainer.getParent());
+        assertEquals(0, ((TestAppWindowToken) appWindowController1.mContainer).positionInParent());
+        assertEquals(1, ((TestAppWindowToken) appWindowController2.mContainer).positionInParent());
+    }
+
     private TestAppWindowContainerController createAppWindowController() {
-        final TestTaskWindowContainerController taskController =
-                new TestTaskWindowContainerController();
+        return createAppWindowController(new TestTaskWindowContainerController());
+    }
+
+    private TestAppWindowContainerController createAppWindowController(
+            TestTaskWindowContainerController taskController) {
         return new TestAppWindowContainerController(taskController);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/DimLayerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/DimLayerControllerTests.java
new file mode 100644
index 0000000..c3a471a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/DimLayerControllerTests.java
@@ -0,0 +1,65 @@
+/*
+ * 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.server.wm;
+
+import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.hardware.display.DisplayManagerGlobal;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.Display;
+import android.view.DisplayInfo;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for the {@link DimLayerController} class.
+ *
+ * Build/Install/Run:
+ *  bit FrameworksServicesTests:com.android.server.wm.DimLayerControllerTests
+ */
+@SmallTest
+@Presubmit
+@org.junit.runner.RunWith(AndroidJUnit4.class)
+public class DimLayerControllerTests extends WindowTestsBase {
+
+    /**
+     * This tests if shared fullscreen dim layer is added when stack is added to display
+     * and is removed when the only stack on the display is removed.
+     */
+    @Test
+    public void testSharedFullScreenDimLayer() throws Exception {
+        // Create a display.
+        final DisplayContent dc = createNewDisplay();
+        assertFalse(dc.mDimLayerController.hasSharedFullScreenDimLayer());
+
+        // Add stack with activity.
+        final TaskStack stack = createTaskStackOnDisplay(dc);
+        assertTrue(dc.mDimLayerController.hasDimLayerUser(stack));
+        assertTrue(dc.mDimLayerController.hasSharedFullScreenDimLayer());
+
+        // Remove the only stack on the display and check if the shared dim layer clears.
+        stack.removeImmediately();
+        assertFalse(dc.mDimLayerController.hasDimLayerUser(stack));
+        assertFalse(dc.mDimLayerController.hasSharedFullScreenDimLayer());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index e54e319..30f99e5 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -29,6 +29,7 @@
 
 import java.util.ArrayList;
 
+import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
@@ -215,13 +216,8 @@
      */
     @Test
     public void testMoveStackBetweenDisplays() throws Exception {
-        // Create second display.
-        final Display display = new Display(DisplayManagerGlobal.getInstance(),
-                sDisplayContent.getDisplayId() + 1, new DisplayInfo(),
-                DEFAULT_DISPLAY_ADJUSTMENTS);
-        final DisplayContent dc = new DisplayContent(display, sWm, sLayersController,
-                new WallpaperController(sWm));
-        sWm.mRoot.addChild(dc, 1);
+        // Create a second display.
+        final DisplayContent dc = createNewDisplay();
 
         // Add stack with activity.
         final TaskStack stack = createTaskStackOnDisplay(dc);
@@ -261,10 +257,31 @@
 
         // Check that override config is applied.
         assertEquals(newOverrideConfig, sDisplayContent.getOverrideConfiguration());
+    }
+
+    /**
+     * This tests global configuration updates when default display config is updated.
+     */
+    @Test
+    public void testDefaultDisplayOverrideConfigUpdate() throws Exception {
+        final Configuration currentOverrideConfig = sDisplayContent.getOverrideConfiguration();
+
+        // Create new, slightly changed override configuration and apply it to the display.
+        final Configuration newOverrideConfig = new Configuration(currentOverrideConfig);
+        newOverrideConfig.densityDpi += 120;
+        newOverrideConfig.fontScale += 0.3;
+
+        sWm.setNewDisplayOverrideConfiguration(newOverrideConfig, DEFAULT_DISPLAY);
 
         // Check that global configuration is updated, as we've updated default display's config.
-        final Configuration globalConfig = sWm.mRoot.getConfiguration();
+        Configuration globalConfig = sWm.mRoot.getConfiguration();
         assertEquals(newOverrideConfig.densityDpi, globalConfig.densityDpi);
         assertEquals(newOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
+
+        // Return back to original values.
+        sWm.setNewDisplayOverrideConfiguration(currentOverrideConfig, DEFAULT_DISPLAY);
+        globalConfig = sWm.mRoot.getConfiguration();
+        assertEquals(currentOverrideConfig.densityDpi, globalConfig.densityDpi);
+        assertEquals(currentOverrideConfig.fontScale, globalConfig.fontScale, 0.1 /* delta */);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
index 7a789d4..b0eba0b 100644
--- a/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
@@ -102,12 +102,7 @@
         task1.mOnDisplayChangedCalled = false;
 
         // Create second display and put second stack on it.
-        final Display display = new Display(DisplayManagerGlobal.getInstance(),
-                sDisplayContent.getDisplayId() + 1, new DisplayInfo(), DEFAULT_DISPLAY_ADJUSTMENTS);
-        final DisplayContent dc = new DisplayContent(display, sWm, sLayersController,
-                new WallpaperController(sWm));
-        sWm.mRoot.addChild(dc, 1);
-
+        final DisplayContent dc = createNewDisplay();
         final StackWindowController stack2Controller =
                 createStackControllerOnDisplay(dc);
         final TaskStack stack2 = stack2Controller.mContainer;
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
index 3ee1da43..f79908e 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
@@ -128,13 +128,10 @@
                 new TestTaskWindowContainerController(stack1Controller);
         final TestTask task1 = (TestTask) taskController.mContainer;
         task1.mOnDisplayChangedCalled = false;
+        assertEquals(sDisplayContent, stack1.getDisplayContent());
 
         // Create second display and put second stack on it.
-        final Display display = new Display(DisplayManagerGlobal.getInstance(),
-                sDisplayContent.getDisplayId() + 1, new DisplayInfo(), DEFAULT_DISPLAY_ADJUSTMENTS);
-        final DisplayContent dc = new DisplayContent(display, sWm, sLayersController,
-                new WallpaperController(sWm));
-        sWm.mRoot.addChild(dc, 1);
+        final DisplayContent dc = createNewDisplay();
         final StackWindowController stack2Controller = createStackControllerOnDisplay(dc);
         final TaskStack stack2 = stack2Controller.mContainer;
         final TestTaskWindowContainerController taskController2 =
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java b/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
index 1514e69..c029a9f 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
@@ -107,4 +107,8 @@
             throws RemoteException {
 
     }
+
+    @Override
+    public void dispatchPointerCaptureChanged(boolean hasCapture) {
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 72157b6..c6f88ed 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -20,7 +20,10 @@
 import android.app.ActivityManagerInternal;
 import android.content.res.Configuration;
 import android.graphics.Rect;
+import android.hardware.display.DisplayManagerGlobal;
 import android.os.Binder;
+import android.view.Display;
+import android.view.DisplayInfo;
 import android.view.IApplicationToken;
 import org.junit.Assert;
 import org.junit.Before;
@@ -40,6 +43,7 @@
 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.content.res.Configuration.EMPTY;
+import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
@@ -65,11 +69,13 @@
     static TestWindowManagerPolicy sPolicy = null;
     private final static IWindow sIWindow = new TestIWindow();
     private final static Session sMockSession = mock(Session.class);
+    private static int sNextDisplayId = Display.DEFAULT_DISPLAY + 1;
     static int sNextStackId = FIRST_DYNAMIC_STACK_ID;
     private static int sNextTaskId = 0;
 
     private static boolean sOneTimeSetupDone = false;
     static DisplayContent sDisplayContent;
+    static DisplayInfo sDisplayInfo = new DisplayInfo();
     static WindowLayersController sLayersController;
     static WindowState sWallpaperWindow;
     static WindowState sImeWindow;
@@ -100,9 +106,15 @@
         if (sDisplayContent != null) {
             sDisplayContent.removeImmediately();
         }
-        sDisplayContent = new DisplayContent(context.getDisplay(), sWm, sLayersController,
-                new WallpaperController(sWm));
-        sWm.mRoot.addChild(sDisplayContent, 0);
+        // Make sure that display ids don't overlap, so there won't be several displays with same
+        // ids among RootWindowContainer children.
+        for (DisplayContent dc : sWm.mRoot.mChildren) {
+            if (dc.getDisplayId() >= sNextDisplayId) {
+                sNextDisplayId = dc.getDisplayId() + 1;
+            }
+        }
+        context.getDisplay().getDisplayInfo(sDisplayInfo);
+        sDisplayContent = createNewDisplay();
         sWm.mDisplayEnabled = true;
         sWm.mDisplayReady = true;
 
@@ -187,7 +199,7 @@
                 true /* onTop */, new Rect(), sWm);
     }
 
-    /**Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
+    /** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
     static Task createTaskInStack(TaskStack stack, int userId) {
         final Task newTask = new Task(sNextTaskId++, stack, userId, sWm, null, EMPTY, false, 0,
                 false, false, new TaskDescription(), null);
@@ -195,6 +207,14 @@
         return newTask;
     }
 
+    /** Creates a {@link DisplayContent} and adds it to the system. */
+    DisplayContent createNewDisplay() {
+        final int displayId = sNextDisplayId++;
+        final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
+                sDisplayInfo, DEFAULT_DISPLAY_ADJUSTMENTS);
+        return new DisplayContent(display, sWm, sLayersController, new WallpaperController(sWm));
+    }
+
     /* Used so we can gain access to some protected members of the {@link WindowToken} class */
     static class TestWindowToken extends WindowToken {
 
@@ -222,6 +242,16 @@
             super(sWm, null, false, dc);
         }
 
+        TestAppWindowToken(WindowManagerService service, IApplicationToken token,
+                boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
+                boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
+                int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
+                boolean alwaysFocusable, AppWindowContainerController controller) {
+            super(service, token, voiceInteraction, dc, inputDispatchingTimeoutNanos, fullscreen,
+                    showForAllUsers, targetSdk, orientation, rotationAnimationHint, configChanges,
+                    launchTaskBehind, alwaysFocusable, controller);
+        }
+
         int getWindowsCount() {
             return mChildren.size();
         }
@@ -237,6 +267,10 @@
         WindowState getLastChild() {
             return mChildren.getLast();
         }
+
+        int positionInParent() {
+            return getParent().mChildren.indexOf(this);
+        }
     }
 
     /* Used so we can gain access to some protected members of the {@link Task} class */
@@ -337,6 +371,19 @@
             mToken = token;
         }
 
+        @Override
+        AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
+                boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
+                boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
+                int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
+                boolean alwaysFocusable, AppWindowContainerController controller) {
+            return new TestAppWindowToken(service, token, voiceInteraction, dc,
+                    inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk,
+                    orientation,
+                    rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
+                    controller);
+        }
+
         AppWindowToken getAppWindowToken() {
             return (AppWindowToken) sDisplayContent.getWindowToken(mToken.asBinder());
         }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index a853d5c..6c45233 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -259,6 +259,12 @@
             KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY = "gsm_nonroaming_networks_string_array";
 
     /**
+     * Override the device's configuration for the ImsService to use for this SIM card.
+     */
+    public static final String KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING =
+            "config_ims_package_override_string";
+
+    /**
      * Override the platform's notion of a network operator being considered roaming.
      * Value is string array of SIDs to be considered roaming for 3GPP2 RATs.
      */
@@ -1396,6 +1402,7 @@
                 });
         sDefaults.putStringArray(KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY, null);
         sDefaults.putStringArray(KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY, null);
+        sDefaults.putString(KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING, null);
         sDefaults.putStringArray(KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY, null);
         sDefaults.putStringArray(KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY, null);
         sDefaults.putStringArray(KEY_DIAL_STRING_REPLACE_STRING_ARRAY, null);
@@ -1558,12 +1565,12 @@
      * moment.
      * </p>
      * <p>Requires that the calling app has carrier privileges.
-     * @see #hasCarrierPrivileges
      * <p>
      * This method returns before the reload has completed, and
      * {@link android.service.carrier.CarrierService#onLoadConfig} will be called from an
      * arbitrary thread.
      * </p>
+     * @see #hasCarrierPrivileges
      */
     public void notifyConfigChangedForSubId(int subId) {
         try {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index b28627b..913da82 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -18,6 +18,7 @@
 
 import static com.android.internal.util.Preconditions.checkNotNull;
 
+import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
@@ -46,8 +47,11 @@
 import android.telecom.PhoneAccountHandle;
 import android.telephony.ClientRequestStats;
 import android.telephony.TelephonyHistogram;
+import android.telephony.ims.feature.ImsFeature;
 import android.util.Log;
 
+import com.android.ims.internal.IImsServiceController;
+import com.android.ims.internal.IImsServiceFeatureListener;
 import com.android.internal.telecom.ITelecomService;
 import com.android.internal.telephony.CellNetworkScanResult;
 import com.android.internal.telephony.IPhoneSubInfo;
@@ -61,6 +65,8 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -373,13 +379,46 @@
             "android.telephony.action.EMERGENCY_ASSISTANCE";
 
     /**
+     * A boolean meta-data value indicating whether the voicemail settings should be hidden in the
+     * call settings page launched by
+     * {@link android.telecom.TelecomManager#ACTION_SHOW_CALL_SETTINGS}.
+     * Dialer implementations (see {@link android.telecom.TelecomManager#getDefaultDialerPackage()})
+     * which would also like to manage voicemail settings should set this meta-data to {@code true}
+     * in the manifest registration of their application.
+     *
+     * @see android.telecom.TelecomManager#ACTION_SHOW_CALL_SETTINGS
+     * @see #ACTION_CONFIGURE_VOICEMAIL
+     * @see #EXTRA_HIDE_PUBLIC_SETTINGS
+     */
+    public static final String METADATA_HIDE_VOICEMAIL_SETTINGS_MENU =
+            "android.telephony.HIDE_VOICEMAIL_SETTINGS_MENU";
+
+    /**
      * Open the voicemail settings activity to make changes to voicemail configuration.
+     *
+     * <p>
+     * The {@link #EXTRA_HIDE_PUBLIC_SETTINGS} hides settings the dialer will modify through public
+     * API if set.
+     *
+     * @see #EXTRA_HIDE_PUBLIC_SETTINGS
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_CONFIGURE_VOICEMAIL =
             "android.telephony.action.CONFIGURE_VOICEMAIL";
 
     /**
+     * The boolean value indicating whether the voicemail settings activity launched by {@link
+     * #ACTION_CONFIGURE_VOICEMAIL} should hide settings accessible through public API. This is
+     * used by dialer implementations which provides their own voicemail settings UI, but still
+     * needs to expose device specific voicemail settings to the user.
+     *
+     * @see #ACTION_CONFIGURE_VOICEMAIL
+     * @see #METADATA_HIDE_VOICEMAIL_SETTINGS_MENU
+     */
+    public static final String EXTRA_HIDE_PUBLIC_SETTINGS =
+            "android.telephony.extra.HIDE_PUBLIC_SETTINGS";
+
+    /**
      * @hide
      */
     public static final boolean EMERGENCY_ASSISTANCE_ENABLED = true;
@@ -388,13 +427,13 @@
      * The lookup key used with the {@link #ACTION_PHONE_STATE_CHANGED} broadcast
      * for a String containing the new call state.
      *
-     * @see #EXTRA_STATE_IDLE
-     * @see #EXTRA_STATE_RINGING
-     * @see #EXTRA_STATE_OFFHOOK
-     *
      * <p class="note">
      * Retrieve with
      * {@link android.content.Intent#getStringExtra(String)}.
+     *
+     * @see #EXTRA_STATE_IDLE
+     * @see #EXTRA_STATE_RINGING
+     * @see #EXTRA_STATE_OFFHOOK
      */
     public static final String EXTRA_STATE = PhoneConstants.STATE_KEY;
 
@@ -1104,12 +1143,12 @@
     /**
      * Returns the neighboring cell information of the device.
      *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}
+     *
      * @return List of NeighboringCellInfo or null if info unavailable.
      *
-     * <p>Requires Permission:
-     * (@link android.Manifest.permission#ACCESS_COARSE_UPDATES}
-     *
-     * @deprecated Use (@link getAllCellInfo} which returns a superset of the information
+     * @deprecated Use {@link #getAllCellInfo} which returns a superset of the information
      *             from NeighboringCellInfo.
      */
     @Deprecated
@@ -1655,6 +1694,11 @@
     /**
      * Returns a constant indicating the radio technology (network type)
      * currently in use on the device for data transmission.
+     *
+     * <p>
+     * Requires Permission:
+     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     *
      * @return the network type
      *
      * @see #NETWORK_TYPE_UNKNOWN
@@ -1673,10 +1717,6 @@
      * @see #NETWORK_TYPE_LTE
      * @see #NETWORK_TYPE_EHRPD
      * @see #NETWORK_TYPE_HSPAP
-     *
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public int getDataNetworkType() {
         return getDataNetworkType(getSubId());
@@ -2657,6 +2697,28 @@
         return false;
     }
 
+
+    /**
+     * Returns the package responsible of processing visual voicemail for the phone account.
+     *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
+     * READ_PHONE_STATE}
+     */
+    @Nullable
+    public String getVisualVoicemailPackageName(PhoneAccountHandle phoneAccountHandle) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony
+                        .getVisualVoicemailPackageName(mContext.getOpPackageName(),
+                                phoneAccountHandle);
+            }
+        } catch (RemoteException ex) {
+        } catch (NullPointerException ex) {
+        }
+        return null;
+    }
+
     /**
      * Enables the visual voicemail SMS filter for a phone account. When the filter is
      * enabled, Incoming SMS messages matching the OMTP VVM SMS interface will be redirected to the
@@ -2851,6 +2913,30 @@
     }
 
     /**
+     * Send the special dialer code. The IPC caller must be the current default dialer.
+     * <p>
+     * Requires Permission:
+     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+     *
+     * @param inputCode The special dialer code to send which follows the format of *#*#<code>#*#*
+     * @return true if sent sucessfully, false otherwise
+     *
+     */
+    public boolean sendDialerCode(String inputCode) {
+        try {
+            final ITelephony telephony = getITelephony();
+            if (telephony == null) {
+                Log.e(TAG, "Telephony service unavailable");
+                return false;
+            }
+            return telephony.sendDialerCode(mContext.getOpPackageName(), inputCode);
+        } catch (RemoteException | NullPointerException ex) {
+            // This could happen before phone restarts due to crashing
+            return false;
+        }
+    }
+
+    /**
      * Returns the IMS private user identity (IMPI) that was loaded from the ISIM.
      * @return the IMPI, or null if not present or not loaded
      * @hide
@@ -4104,6 +4190,37 @@
         }
     }
 
+    /** @hide */
+    @IntDef({ImsFeature.EMERGENCY_MMTEL, ImsFeature.MMTEL, ImsFeature.RCS})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Feature {}
+
+    /**
+     * Returns the {@link IImsServiceController} that corresponds to the given slot Id and IMS
+     * feature or {@link null} if the service is not available. If an ImsServiceController is
+     * available, the {@link IImsServiceFeatureListener} callback is registered as a listener for
+     * feature updates.
+     * @param slotId The SIM slot that we are requesting the {@link IImsServiceController} for.
+     * @param feature The IMS Feature we are requesting, corresponding to {@link ImsFeature}.
+     * @param callback Listener that will send updates to ImsManager when there are updates to
+     * ImsServiceController.
+     * @return {@link IImsServiceController} interface for the feature specified or {@link null} if
+     * it is unavailable.
+     * @hide
+     */
+    public IImsServiceController getImsServiceControllerAndListen(int slotId, @Feature int feature,
+            IImsServiceFeatureListener callback) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.getImsServiceControllerAndListen(slotId, feature, callback);
+            }
+        } catch (RemoteException e) {
+            Rlog.e(TAG, "getImsServiceControllerAndListen, RemoteException: " + e.getMessage());
+        }
+        return null;
+    }
+
     /**
      * Set IMS registration state
      *
diff --git a/core/java/com/android/internal/logging/legacy/SysuiQueryParser.java b/telephony/java/android/telephony/ims/ImsServiceBase.java
similarity index 60%
copy from core/java/com/android/internal/logging/legacy/SysuiQueryParser.java
copy to telephony/java/android/telephony/ims/ImsServiceBase.java
index 7b3c0a7..0b50eca 100644
--- a/core/java/com/android/internal/logging/legacy/SysuiQueryParser.java
+++ b/telephony/java/android/telephony/ims/ImsServiceBase.java
@@ -11,22 +11,25 @@
  * 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.
+ * limitations under the License
  */
-package com.android.internal.logging.legacy;
+
+package android.telephony.ims;
+
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
 
 /**
- * Parse the Android framework sysui search query logs.
- * For now just treat them like actions.
+ * Base ImsService Implementation, which is used by the ImsResolver to bind.
  * @hide
  */
-public class SysuiQueryParser extends SysuiActionParser {
-    private static final String TAG = "SysuiQueryParser";
-
-    private static final int EVENTLOG_TAG = 524289;
+@SystemApi
+public class ImsServiceBase extends Service {
 
     @Override
-    public int getTag() {
-        return EVENTLOG_TAG;
+    public IBinder onBind(Intent intent) {
+        return null;
     }
 }
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
new file mode 100644
index 0000000..0509d60
--- /dev/null
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -0,0 +1,33 @@
+/*
+ * 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.ims.feature;
+
+/**
+ * Base class for all IMS features that are supported by the framework.
+ * @hide
+ */
+public class ImsFeature {
+
+    // Invalid feature value
+    public static final int INVALID = -1;
+    // ImsFeatures that are defined in the Manifests
+    public static final int EMERGENCY_MMTEL = 0;
+    public static final int MMTEL = 1;
+    public static final int RCS = 2;
+    // Total number of features defined
+    public static final int MAX = 3;
+}
diff --git a/telephony/java/com/android/ims/internal/IImsServiceController.aidl b/telephony/java/com/android/ims/internal/IImsServiceController.aidl
new file mode 100644
index 0000000..fa86a43
--- /dev/null
+++ b/telephony/java/com/android/ims/internal/IImsServiceController.aidl
@@ -0,0 +1,25 @@
+/*
+ * 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.ims.internal;
+
+/**
+ * {@hide}
+ */
+interface IImsServiceController {
+    void createImsFeature(int slotId, int feature);
+    void removeImsFeature(int slotId, int feature);
+}
diff --git a/telephony/java/com/android/ims/internal/IImsServiceFeatureListener.aidl b/telephony/java/com/android/ims/internal/IImsServiceFeatureListener.aidl
new file mode 100644
index 0000000..0a36b6b
--- /dev/null
+++ b/telephony/java/com/android/ims/internal/IImsServiceFeatureListener.aidl
@@ -0,0 +1,25 @@
+/*
+ * 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.ims.internal;
+
+/**
+ * {@hide}
+ */
+oneway interface IImsServiceFeatureListener {
+    void imsFeatureCreated(int slotId, int feature);
+    void imsFeatureRemoved(int slotId, int feature);
+}
\ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 9a9a092..f2b8804 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -33,6 +33,8 @@
 import android.telephony.ServiceState;
 import android.telephony.TelephonyHistogram;
 import android.telephony.VisualVoicemailSmsFilterSettings;
+import com.android.ims.internal.IImsServiceController;
+import com.android.ims.internal.IImsServiceFeatureListener;
 import com.android.internal.telephony.CellNetworkScanResult;
 import com.android.internal.telephony.OperatorInfo;
 
@@ -478,6 +480,9 @@
     boolean isVisualVoicemailEnabled(String callingPackage,
             in PhoneAccountHandle accountHandle);
 
+    String getVisualVoicemailPackageName(String callingPackage,
+            in PhoneAccountHandle phoneAccountHandle);
+
     // Not oneway, caller needs to make sure the vaule is set before receiving a SMS
     void enableVisualVoicemailSmsFilter(String callingPackage, int subId,
             in VisualVoicemailSmsFilterSettings settings);
@@ -501,6 +506,9 @@
     oneway void sendVisualVoicemailSmsForSubscriber(in String callingPackage, in int subId,
             in String number, in int port, in String text, in PendingIntent sentIntent);
 
+    // Send the special dialer code. The IPC caller must be the current default dialer.
+    boolean sendDialerCode(String callingPackageName, String inputCode);
+
     /**
      * Returns the network type for data transmission
      * Legacy call, permission-free
@@ -742,6 +750,14 @@
     int getTetherApnRequired();
 
     /**
+     *  Get ImsServiceController binder from ImsResolver that corresponds to the subId and feature
+     *  requested as well as registering the ImsServiceController for callbacks using the
+     *  IImsServiceFeatureListener interface.
+     */
+    IImsServiceController getImsServiceControllerAndListen(int slotId, int feature,
+                IImsServiceFeatureListener callback);
+
+    /**
      * Set the network selection mode to automatic.
      *
      * @param subId the id of the subscription to update.
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 0c34f20..71c9c73 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -149,6 +149,12 @@
         throw new UnsupportedOperationException();
     }
 
+    /** @hide */
+    @Override
+    public boolean isPermissionReviewModeEnabled() {
+        return false;
+    }
+
     @Override
     public PermissionGroupInfo getPermissionGroupInfo(String name,
             int flags) throws NameNotFoundException {
@@ -220,6 +226,11 @@
     }
 
     @Override
+    public boolean canRequestPackageInstalls() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public boolean isPermissionRevokedByPolicy(String permName, String pkgName) {
         throw new UnsupportedOperationException();
     }
diff --git a/tests/UiBench/AndroidManifest.xml b/tests/UiBench/AndroidManifest.xml
index 0681b61..07f7617 100644
--- a/tests/UiBench/AndroidManifest.xml
+++ b/tests/UiBench/AndroidManifest.xml
@@ -100,6 +100,15 @@
             </intent-filter>
         </activity>
         <activity
+            android:name=".ClippedListActivity"
+            android:label="General/Clipped ListView"
+            android:theme="@style/NoActionBar">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.test.uibench.TEST" />
+            </intent-filter>
+        </activity>
+        <activity
             android:name=".TrivialRecyclerViewActivity"
             android:label="General/Trivial RecyclerView" >
             <intent-filter>
diff --git a/tests/UiBench/res/layout/app_bar_navigation_drawer.xml b/tests/UiBench/res/layout/app_bar_navigation_drawer.xml
index ede2a56..5657587 100644
--- a/tests/UiBench/res/layout/app_bar_navigation_drawer.xml
+++ b/tests/UiBench/res/layout/app_bar_navigation_drawer.xml
@@ -16,6 +16,7 @@
   -->
 <android.support.design.widget.CoordinatorLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/app_bar_layout"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:fitsSystemWindows="true">
diff --git a/tests/UiBench/src/com/android/test/uibench/ClippedListActivity.java b/tests/UiBench/src/com/android/test/uibench/ClippedListActivity.java
new file mode 100644
index 0000000..7454124
--- /dev/null
+++ b/tests/UiBench/src/com/android/test/uibench/ClippedListActivity.java
@@ -0,0 +1,66 @@
+/*
+ * 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.test.uibench;
+
+import android.os.Bundle;
+import android.support.design.widget.NavigationView;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.ListFragment;
+import android.support.v4.view.GravityCompat;
+import android.support.v4.widget.DrawerLayout;
+import android.support.v7.app.ActionBarDrawerToggle;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.MenuItem;
+import android.widget.ArrayAdapter;
+import android.widget.ListAdapter;
+
+public class ClippedListActivity extends AppCompatActivity
+        implements NavigationView.OnNavigationItemSelectedListener {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_navigation_drawer);
+        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+        setSupportActionBar(toolbar);
+        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
+        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
+                this, drawer, toolbar, R.string.navigation_drawer_open,
+                R.string.navigation_drawer_close);
+        drawer.setDrawerListener(toggle);
+        toggle.syncState();
+
+        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
+        navigationView.setNavigationItemSelectedListener(this);
+
+        FragmentManager fm = getSupportFragmentManager();
+        if (fm.findFragmentById(android.R.id.content) == null) {
+            ListFragment listFragment = new ListFragment();
+            ListAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1,
+                    TextUtils.buildSimpleStringList(40));
+            listFragment.setListAdapter(adapter);
+            fm.beginTransaction().add(R.id.app_bar_layout, listFragment).commit();
+        }
+    }
+
+    @Override
+    public boolean onNavigationItemSelected(MenuItem item) {
+        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
+        drawer.closeDrawer(GravityCompat.START);
+        return true;
+    }
+}
diff --git a/tests/UiBench/src/com/android/test/uibench/TextUtils.java b/tests/UiBench/src/com/android/test/uibench/TextUtils.java
index d88ca1e..32a5986 100644
--- a/tests/UiBench/src/com/android/test/uibench/TextUtils.java
+++ b/tests/UiBench/src/com/android/test/uibench/TextUtils.java
@@ -35,10 +35,14 @@
     }
 
     public static String[] buildSimpleStringList() {
+        return buildSimpleStringList(SIMPLE_STRING_LENGTH);
+    }
+
+    public static String[] buildSimpleStringList(int stringLength) {
         String[] strings = new String[STRING_COUNT];
         Random random = new Random(0);
         for (int i = 0; i < strings.length; i++) {
-            strings[i] = randomWord(random, SIMPLE_STRING_LENGTH);
+            strings[i] = randomWord(random, stringLength);
         }
         return strings;
     }
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 46b6403..2d7a68f 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -68,7 +68,6 @@
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.test.AndroidTestCase;
-import android.test.FlakyTest;
 import android.test.mock.MockContentResolver;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
@@ -154,49 +153,32 @@
     }
 
     /**
-     * A subclass of HandlerThread that allows callers to wait for it to become idle. waitForIdle
-     * will return immediately if the handler is already idle.
+     * Block until the given handler becomes idle, or until timeoutMs has passed.
      */
-    private class IdleableHandlerThread extends HandlerThread {
-        private IdleHandler mIdleHandler;
-
-        public IdleableHandlerThread(String name) {
-            super(name);
-        }
-
-        public void waitForIdle(int timeoutMs) {
-            final ConditionVariable cv = new ConditionVariable();
-            final MessageQueue queue = getLooper().getQueue();
-
+    private static void waitForIdleHandler(HandlerThread handler, int timeoutMs) {
+        final ConditionVariable cv = new ConditionVariable();
+        final MessageQueue queue = handler.getLooper().getQueue();
+        final IdleHandler idleHandler = () -> {
             synchronized (queue) {
-                if (queue.isIdle()) {
-                    return;
-                }
-
-                assertNull("BUG: only one idle handler allowed", mIdleHandler);
-                mIdleHandler = new IdleHandler() {
-                    public boolean queueIdle() {
-                        synchronized (queue) {
-                            cv.open();
-                            mIdleHandler = null;
-                            return false;  // Remove the handler.
-                        }
-                    }
-                };
-                queue.addIdleHandler(mIdleHandler);
+                cv.open();
+                return false; // Remove the idleHandler.
             }
-
-            if (!cv.block(timeoutMs)) {
-                fail("HandlerThread " + getName() +
-                        " did not become idle after " + timeoutMs + " ms");
-                queue.removeIdleHandler(mIdleHandler);
+        };
+        synchronized (queue) {
+            if (queue.isIdle()) {
+                return;
             }
+            queue.addIdleHandler(idleHandler);
+        }
+        if (!cv.block(timeoutMs)) {
+            fail("HandlerThread " + handler.getName() +
+                    " did not become idle after " + timeoutMs + " ms");
+            queue.removeIdleHandler(idleHandler);
         }
     }
 
-    // Tests that IdleableHandlerThread works as expected.
     @SmallTest
-    public void testIdleableHandlerThread() {
+    public void testWaitForIdle() {
         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
 
         // Tests that waitForIdle returns immediately if the service is already idle.
@@ -220,9 +202,9 @@
         }
     }
 
-    @SmallTest
-    @FlakyTest(tolerance = 3)
-    public void testNotWaitingForIdleCausesRaceConditions() {
+    // This test has an inherent race condition in it, and cannot be enabled for continuous testing
+    // or presubmit tests. It is kept for manual runs and documentation purposes.
+    public void verifyThatNotWaitingForIdleCausesRaceConditions() {
         // Bring up a network that we can use to send messages to ConnectivityService.
         ConditionVariable cv = waitForConnectivityBroadcasts(1);
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
@@ -249,7 +231,7 @@
         private final WrappedNetworkMonitor mWrappedNetworkMonitor;
         private final NetworkInfo mNetworkInfo;
         private final NetworkCapabilities mNetworkCapabilities;
-        private final IdleableHandlerThread mHandlerThread;
+        private final HandlerThread mHandlerThread;
         private final ConditionVariable mDisconnected = new ConditionVariable();
         private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
         private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
@@ -281,7 +263,7 @@
                 default:
                     throw new UnsupportedOperationException("unimplemented network type");
             }
-            mHandlerThread = new IdleableHandlerThread("Mock-" + typeName);
+            mHandlerThread = new HandlerThread("Mock-" + typeName);
             mHandlerThread.start();
             mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
                     "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
@@ -321,7 +303,7 @@
         }
 
         public void waitForIdle(int timeoutMs) {
-            mHandlerThread.waitForIdle(timeoutMs);
+            waitForIdleHandler(mHandlerThread, timeoutMs);
         }
 
         public void waitForIdle() {
@@ -648,11 +630,6 @@
         }
 
         @Override
-        protected HandlerThread createHandlerThread() {
-            return new IdleableHandlerThread("WrappedConnectivityService");
-        }
-
-        @Override
         protected int getDefaultTcpRwnd() {
             // Prevent wrapped ConnectivityService from trying to write to SystemProperties.
             return 0;
@@ -710,7 +687,7 @@
         }
 
         public void waitForIdle(int timeoutMs) {
-            ((IdleableHandlerThread) mHandlerThread).waitForIdle(timeoutMs);
+            waitForIdleHandler(mHandlerThread, timeoutMs);
         }
 
         public void waitForIdle() {
@@ -1135,7 +1112,7 @@
         // Chosen to be much less than the linger timeout. This ensures that we can distinguish
         // between a LOST callback that arrives immediately and a LOST callback that arrives after
         // the linger timeout.
-        private final static int TIMEOUT_MS = 50;
+        private final static int TIMEOUT_MS = 100;
 
         private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
 
@@ -1487,8 +1464,8 @@
 
         // Let linger run its course.
         callback.assertNoCallback();
-        callback.expectCallback(CallbackState.LOST, mCellNetworkAgent,
-                TEST_LINGER_DELAY_MS /* timeoutMs */);
+        final int lingerTimeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
+        callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
 
         // Clean up.
         mWiFiNetworkAgent.disconnect();
@@ -1977,7 +1954,9 @@
         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
 
         // When lingering is complete, cell is still there but is now in the background.
-        fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, TEST_LINGER_DELAY_MS);
+        mService.waitForIdle();
+        int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
+        fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
         callback.assertNoCallback();
         assertFalse(isForegroundNetwork(mCellNetworkAgent));
         assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
@@ -2003,6 +1982,7 @@
 
         // Disconnect wifi and check that cell is foreground again.
         mWiFiNetworkAgent.disconnect();
+        mService.waitForIdle();
         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
         fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
         fgCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
@@ -2339,14 +2319,14 @@
         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
                 NetworkCapabilities.TRANSPORT_WIFI).build();
         final TestNetworkCallback networkCallback = new TestNetworkCallback();
-        mCm.requestNetwork(nr, networkCallback, 10);
+        final int timeoutMs = 150;
+        mCm.requestNetwork(nr, networkCallback, timeoutMs);
 
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(false);
-        networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent, timeoutMs);
 
         // pass timeout and validate that UNAVAILABLE is not called
-        sleepFor(15);
         networkCallback.assertNoCallback();
     }
 
@@ -2359,17 +2339,19 @@
         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
                 NetworkCapabilities.TRANSPORT_WIFI).build();
         final TestNetworkCallback networkCallback = new TestNetworkCallback();
-        mCm.requestNetwork(nr, networkCallback, 500);
+        final int requestTimeoutMs = 100;
+        mCm.requestNetwork(nr, networkCallback, requestTimeoutMs);
 
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(false);
-        networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+        final int assertTimeoutMs = 150;
+        networkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent, assertTimeoutMs);
         sleepFor(20);
         mWiFiNetworkAgent.disconnect();
         networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
 
         // pass timeout and validate that UNAVAILABLE is not called
-        sleepFor(600);
+        sleepFor(100);
         networkCallback.assertNoCallback();
     }
 
@@ -2383,7 +2365,8 @@
         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
                 NetworkCapabilities.TRANSPORT_WIFI).build();
         final TestNetworkCallback networkCallback = new TestNetworkCallback();
-        mCm.requestNetwork(nr, networkCallback, 10);
+        final int timeoutMs = 10;
+        mCm.requestNetwork(nr, networkCallback, timeoutMs);
 
         // pass timeout and validate that UNAVAILABLE is called
         networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
@@ -2403,7 +2386,8 @@
         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
                 NetworkCapabilities.TRANSPORT_WIFI).build();
         final TestNetworkCallback networkCallback = new TestNetworkCallback();
-        mCm.requestNetwork(nr, networkCallback, 10);
+        final int timeoutMs = 10;
+        mCm.requestNetwork(nr, networkCallback, timeoutMs);
 
         // remove request
         mCm.unregisterNetworkCallback(networkCallback);
@@ -2420,13 +2404,13 @@
         networkCallback.assertNoCallback();
     }
 
-    public void assertEventuallyTrue(BooleanSupplier fn, long maxWaitingTimeMs) throws Exception {
+    public void assertEventuallyTrue(BooleanSupplier fn, long maxWaitingTimeMs) {
         long start = SystemClock.elapsedRealtime();
         while (SystemClock.elapsedRealtime() <= start + maxWaitingTimeMs) {
             if (fn.getAsBoolean()) {
                 return;
             }
-            Thread.sleep(10);
+            sleepFor(15);
         }
         assertTrue(fn.getAsBoolean());
     }
@@ -2594,7 +2578,9 @@
         callback.expectError(PacketKeepalive.ERROR_INVALID_NETWORK);
 
         // ... and that stopping it after that has no adverse effects.
-        assertNull(mCm.getNetworkCapabilities(myNet));
+        // TODO: investigate assertEventuallyTrue is needed and waitForIdle() is not enough
+        final Network myNetAlias = myNet;
+        assertEventuallyTrue(() -> mCm.getNetworkCapabilities(myNetAlias) == null, 100);
         ka.stop();
 
         // Reconnect.
@@ -2838,11 +2824,11 @@
     }
 
     /* test utilities */
+    // TODO: eliminate all usages of sleepFor and replace by proper timeouts/waitForIdle.
     static private void sleepFor(int ms) {
         try {
             Thread.sleep(ms);
         } catch (InterruptedException e) {
         }
-
     }
 }
diff --git a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
index 1e67769..b8c739b 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
@@ -91,12 +91,12 @@
     }
 
     @Test
-    public void testListensForDunNetworks() throws Exception {
+    public void testListensForAllNetworks() throws Exception {
         assertTrue(mCM.listening.isEmpty());
 
         mUNM.start();
         assertFalse(mCM.listening.isEmpty());
-        assertTrue(mCM.isListeningForDun());
+        assertTrue(mCM.isListeningForAll());
 
         mUNM.stop();
         assertTrue(mCM.hasNoCallbacks());
@@ -197,9 +197,12 @@
                    legacyTypeMap.isEmpty();
         }
 
-        boolean isListeningForDun() {
+        boolean isListeningForAll() {
+            final NetworkCapabilities empty = new NetworkCapabilities();
+            empty.clearAll();
+
             for (NetworkRequest req : listening.values()) {
-                if (req.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)) {
+                if (req.networkCapabilities.equalRequestableCapabilities(empty)) {
                     return true;
                 }
             }
diff --git a/tools/incident_report/Android.mk b/tools/incident_report/Android.mk
index 9e56e3d..e57a959 100644
--- a/tools/incident_report/Android.mk
+++ b/tools/incident_report/Android.mk
@@ -34,6 +34,9 @@
     libplatformprotos \
     libprotobuf-cpp-full
 
+# b/34740546, work around clang-tidy segmentation fault.
+LOCAL_TIDY_CHECKS := -modernize*
+
 LOCAL_C_FLAGS := \
     -Wno-unused-parameter
 include $(BUILD_HOST_EXECUTABLE)
diff --git a/tools/incident_section_gen/Android.mk b/tools/incident_section_gen/Android.mk
index acf3f83..0549026 100644
--- a/tools/incident_section_gen/Android.mk
+++ b/tools/incident_section_gen/Android.mk
@@ -21,6 +21,8 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := incident-section-gen
+# b/34740546, work around clang-tidy segmentation fault.
+LOCAL_TIDY_CHECKS := -modernize*
 LOCAL_CFLAGS += -g -O0
 LOCAL_C_INCLUDES := \
     external/protobuf/src
diff --git a/tools/layoutlib/bridge/src/android/view/textservice/TextServicesManager.java b/tools/layoutlib/bridge/src/android/view/textservice/TextServicesManager.java
index 06874bd..8e1f218 100644
--- a/tools/layoutlib/bridge/src/android/view/textservice/TextServicesManager.java
+++ b/tools/layoutlib/bridge/src/android/view/textservice/TextServicesManager.java
@@ -16,208 +16,43 @@
 
 package android.view.textservice;
 
-import com.android.internal.textservice.ISpellCheckerSessionListener;
-import com.android.internal.textservice.ITextServicesManager;
-import com.android.internal.textservice.ITextServicesSessionListener;
-
-import android.content.Context;
 import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Log;
 import android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener;
 
 import java.util.Locale;
 
 /**
- * System API to the overall text services, which arbitrates interaction between applications
- * and text services. You can retrieve an instance of this interface with
- * {@link Context#getSystemService(String) Context.getSystemService()}.
- *
- * The user can change the current text services in Settings. And also applications can specify
- * the target text services.
- *
- * <h3>Architecture Overview</h3>
- *
- * <p>There are three primary parties involved in the text services
- * framework (TSF) architecture:</p>
- *
- * <ul>
- * <li> The <strong>text services manager</strong> as expressed by this class
- * is the central point of the system that manages interaction between all
- * other parts.  It is expressed as the client-side API here which exists
- * in each application context and communicates with a global system service
- * that manages the interaction across all processes.
- * <li> A <strong>text service</strong> implements a particular
- * interaction model allowing the client application to retrieve information of text.
- * The system binds to the current text service that is in use, causing it to be created and run.
- * <li> Multiple <strong>client applications</strong> arbitrate with the text service
- * manager for connections to text services.
- * </ul>
- *
- * <h3>Text services sessions</h3>
- * <ul>
- * <li>The <strong>spell checker session</strong> is one of the text services.
- * {@link android.view.textservice.SpellCheckerSession}</li>
- * </ul>
- *
+ * A stub class of TextServicesManager for Layout-Lib.
  */
 public final class TextServicesManager {
-    private static final String TAG = TextServicesManager.class.getSimpleName();
-    private static final boolean DBG = false;
-
-    private static TextServicesManager sInstance;
-
-    private final ITextServicesManager mService;
-
-    private TextServicesManager() {
-        mService = new FakeTextServicesManager();
-    }
+    private static final TextServicesManager sInstance = new TextServicesManager();
+    private static final SpellCheckerInfo[] EMPTY_SPELL_CHECKER_INFO = new SpellCheckerInfo[0];
 
     /**
      * Retrieve the global TextServicesManager instance, creating it if it doesn't already exist.
      * @hide
      */
     public static TextServicesManager getInstance() {
-        synchronized (TextServicesManager.class) {
-            if (sInstance == null) {
-                sInstance = new TextServicesManager();
-            }
-            return sInstance;
-        }
+        return sInstance;
     }
 
-    /**
-     * Returns the language component of a given locale string.
-     */
-    private static String parseLanguageFromLocaleString(String locale) {
-        final int idx = locale.indexOf('_');
-        if (idx < 0) {
-            return locale;
-        } else {
-            return locale.substring(0, idx);
-        }
-    }
-
-    /**
-     * Get a spell checker session for the specified spell checker
-     * @param locale the locale for the spell checker. If {@code locale} is null and
-     * referToSpellCheckerLanguageSettings is true, the locale specified in Settings will be
-     * returned. If {@code locale} is not null and referToSpellCheckerLanguageSettings is true,
-     * the locale specified in Settings will be returned only when it is same as {@code locale}.
-     * Exceptionally, when referToSpellCheckerLanguageSettings is true and {@code locale} is
-     * only language (e.g. "en"), the specified locale in Settings (e.g. "en_US") will be
-     * selected.
-     * @param listener a spell checker session lister for getting results from a spell checker.
-     * @param referToSpellCheckerLanguageSettings if true, the session for one of enabled
-     * languages in settings will be returned.
-     * @return the spell checker session of the spell checker
-     */
     public SpellCheckerSession newSpellCheckerSession(Bundle bundle, Locale locale,
             SpellCheckerSessionListener listener, boolean referToSpellCheckerLanguageSettings) {
-        if (listener == null) {
-            throw new NullPointerException();
-        }
-        if (!referToSpellCheckerLanguageSettings && locale == null) {
-            throw new IllegalArgumentException("Locale should not be null if you don't refer"
-                    + " settings.");
-        }
-
-        if (referToSpellCheckerLanguageSettings && !isSpellCheckerEnabled()) {
-            return null;
-        }
-
-        final SpellCheckerInfo sci;
-        try {
-            sci = mService.getCurrentSpellChecker(null);
-        } catch (RemoteException e) {
-            return null;
-        }
-        if (sci == null) {
-            return null;
-        }
-        SpellCheckerSubtype subtypeInUse = null;
-        if (referToSpellCheckerLanguageSettings) {
-            subtypeInUse = getCurrentSpellCheckerSubtype(true);
-            if (subtypeInUse == null) {
-                return null;
-            }
-            if (locale != null) {
-                final String subtypeLocale = subtypeInUse.getLocale();
-                final String subtypeLanguage = parseLanguageFromLocaleString(subtypeLocale);
-                if (subtypeLanguage.length() < 2 || !locale.getLanguage().equals(subtypeLanguage)) {
-                    return null;
-                }
-            }
-        } else {
-            final String localeStr = locale.toString();
-            for (int i = 0; i < sci.getSubtypeCount(); ++i) {
-                final SpellCheckerSubtype subtype = sci.getSubtypeAt(i);
-                final String tempSubtypeLocale = subtype.getLocale();
-                final String tempSubtypeLanguage = parseLanguageFromLocaleString(tempSubtypeLocale);
-                if (tempSubtypeLocale.equals(localeStr)) {
-                    subtypeInUse = subtype;
-                    break;
-                } else if (tempSubtypeLanguage.length() >= 2 &&
-                        locale.getLanguage().equals(tempSubtypeLanguage)) {
-                    subtypeInUse = subtype;
-                }
-            }
-        }
-        if (subtypeInUse == null) {
-            return null;
-        }
-        final SpellCheckerSession session = new SpellCheckerSession(
-                sci, mService, listener, subtypeInUse);
-        try {
-            mService.getSpellCheckerService(sci.getId(), subtypeInUse.getLocale(),
-                    session.getTextServicesSessionListener(),
-                    session.getSpellCheckerSessionListener(), bundle);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-        return session;
+        return null;
     }
 
     /**
      * @hide
      */
     public SpellCheckerInfo[] getEnabledSpellCheckers() {
-        try {
-            final SpellCheckerInfo[] retval = mService.getEnabledSpellCheckers();
-            if (DBG) {
-                Log.d(TAG, "getEnabledSpellCheckers: " + (retval != null ? retval.length : "null"));
-            }
-            return retval;
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return EMPTY_SPELL_CHECKER_INFO;
     }
 
     /**
      * @hide
      */
     public SpellCheckerInfo getCurrentSpellChecker() {
-        try {
-            // Passing null as a locale for ICS
-            return mService.getCurrentSpellChecker(null);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void setCurrentSpellChecker(SpellCheckerInfo sci) {
-        try {
-            if (sci == null) {
-                throw new NullPointerException("SpellCheckerInfo is null.");
-            }
-            mService.setCurrentSpellChecker(null, sci.getId());
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return null;
     }
 
     /**
@@ -225,118 +60,13 @@
      */
     public SpellCheckerSubtype getCurrentSpellCheckerSubtype(
             boolean allowImplicitlySelectedSubtype) {
-        try {
-            // Passing null as a locale until we support multiple enabled spell checker subtypes.
-            return mService.getCurrentSpellCheckerSubtype(null, allowImplicitlySelectedSubtype);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void setSpellCheckerSubtype(SpellCheckerSubtype subtype) {
-        try {
-            final int hashCode;
-            if (subtype == null) {
-                hashCode = 0;
-            } else {
-                hashCode = subtype.hashCode();
-            }
-            mService.setCurrentSpellCheckerSubtype(null, hashCode);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void setSpellCheckerEnabled(boolean enabled) {
-        try {
-            mService.setSpellCheckerEnabled(enabled);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return null;
     }
 
     /**
      * @hide
      */
     public boolean isSpellCheckerEnabled() {
-        try {
-            return mService.isSpellCheckerEnabled();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        return false;
     }
-
-    private static class FakeTextServicesManager implements ITextServicesManager {
-
-        @Override
-        public void finishSpellCheckerService(ISpellCheckerSessionListener arg0)
-                throws RemoteException {
-            // TODO Auto-generated method stub
-
-        }
-
-        @Override
-        public SpellCheckerInfo getCurrentSpellChecker(String arg0) throws RemoteException {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        @Override
-        public SpellCheckerSubtype getCurrentSpellCheckerSubtype(String arg0, boolean arg1)
-                throws RemoteException {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        @Override
-        public SpellCheckerInfo[] getEnabledSpellCheckers() throws RemoteException {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        @Override
-        public void getSpellCheckerService(String arg0, String arg1,
-                ITextServicesSessionListener arg2, ISpellCheckerSessionListener arg3, Bundle arg4)
-                throws RemoteException {
-            // TODO Auto-generated method stub
-
-        }
-
-        @Override
-        public boolean isSpellCheckerEnabled() throws RemoteException {
-            // TODO Auto-generated method stub
-            return false;
-        }
-
-        @Override
-        public void setCurrentSpellChecker(String arg0, String arg1) throws RemoteException {
-            // TODO Auto-generated method stub
-
-        }
-
-        @Override
-        public void setCurrentSpellCheckerSubtype(String arg0, int arg1) throws RemoteException {
-            // TODO Auto-generated method stub
-
-        }
-
-        @Override
-        public void setSpellCheckerEnabled(boolean arg0) throws RemoteException {
-            // TODO Auto-generated method stub
-
-        }
-
-        @Override
-        public IBinder asBinder() {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-    }
-}
\ No newline at end of file
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index d3ec9e2..de04c43 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -145,6 +145,11 @@
     }
 
     @Override
+    public boolean isPermissionReviewModeEnabled() {
+        return false;
+    }
+
+    @Override
     public PermissionGroupInfo getPermissionGroupInfo(String name, int flags)
             throws NameNotFoundException {
         return null;
@@ -891,4 +896,9 @@
     public int getInstallReason(String packageName, UserHandle user) {
         return INSTALL_REASON_UNKNOWN;
     }
+
+    @Override
+    public boolean canRequestPackageInstalls() {
+        return false;
+    }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
index a83f100..a51ad2e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
@@ -108,6 +108,10 @@
     }
 
     @Override
+    public void dispatchPointerCaptureChanged(boolean hasCapture) {
+    }
+
+    @Override
     public IBinder asBinder() {
         // pass for now.
         return null;
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index e410a9c..0bfb955 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -142,7 +142,7 @@
     private HashMap<String, String> mFields = new HashMap<String, String>();
     private X509Certificate[] mCaCerts;
     private PrivateKey mClientPrivateKey;
-    private X509Certificate mClientCertificate;
+    private X509Certificate[] mClientCertificateChain;
     private int mEapMethod = Eap.NONE;
     private int mPhase2Method = Phase2.NONE;
 
@@ -161,9 +161,19 @@
         for (String key : source.mFields.keySet()) {
             mFields.put(key, source.mFields.get(key));
         }
-        mCaCerts = source.mCaCerts;
+        if (source.mCaCerts != null) {
+            mCaCerts = Arrays.copyOf(source.mCaCerts, source.mCaCerts.length);
+        } else {
+            mCaCerts = null;
+        }
         mClientPrivateKey = source.mClientPrivateKey;
-        mClientCertificate = source.mClientCertificate;
+        if (source.mClientCertificateChain != null) {
+            mClientCertificateChain = Arrays.copyOf(
+                    source.mClientCertificateChain,
+                    source.mClientCertificateChain.length);
+        } else {
+            mClientCertificateChain = null;
+        }
         mEapMethod = source.mEapMethod;
         mPhase2Method = source.mPhase2Method;
     }
@@ -185,7 +195,7 @@
         dest.writeInt(mPhase2Method);
         ParcelUtil.writeCertificates(dest, mCaCerts);
         ParcelUtil.writePrivateKey(dest, mClientPrivateKey);
-        ParcelUtil.writeCertificate(dest, mClientCertificate);
+        ParcelUtil.writeCertificates(dest, mClientCertificateChain);
     }
 
     public static final Creator<WifiEnterpriseConfig> CREATOR =
@@ -204,7 +214,7 @@
                     enterpriseConfig.mPhase2Method = in.readInt();
                     enterpriseConfig.mCaCerts = ParcelUtil.readCertificates(in);
                     enterpriseConfig.mClientPrivateKey = ParcelUtil.readPrivateKey(in);
-                    enterpriseConfig.mClientCertificate = ParcelUtil.readCertificate(in);
+                    enterpriseConfig.mClientCertificateChain = ParcelUtil.readCertificates(in);
                     return enterpriseConfig;
                 }
 
@@ -742,10 +752,54 @@
      * @throws IllegalArgumentException for an invalid key or certificate.
      */
     public void setClientKeyEntry(PrivateKey privateKey, X509Certificate clientCertificate) {
+        X509Certificate[] clientCertificates = null;
         if (clientCertificate != null) {
-            if (clientCertificate.getBasicConstraints() != -1) {
-                throw new IllegalArgumentException("Cannot be a CA certificate");
+            clientCertificates = new X509Certificate[] {clientCertificate};
+        }
+        setClientKeyEntryWithCertificateChain(privateKey, clientCertificates);
+    }
+
+    /**
+     * Specify a private key and client certificate chain for client authorization.
+     *
+     * <p>A default name is automatically assigned to the key entry and used
+     * with this configuration.  The framework takes care of installing the
+     * key entry when the config is saved and removing the key entry when
+     * the config is removed.
+
+     * @param privateKey
+     * @param clientCertificateChain
+     * @throws IllegalArgumentException for an invalid key or certificate.
+     */
+    public void setClientKeyEntryWithCertificateChain(PrivateKey privateKey,
+            X509Certificate[] clientCertificateChain) {
+        X509Certificate[] newCerts = null;
+        if (clientCertificateChain != null && clientCertificateChain.length > 0) {
+            // We validate that this is a well formed chain that starts
+            // with an end-certificate and is followed by CA certificates.
+            // We don't validate that each following certificate verifies
+            // the previous. https://en.wikipedia.org/wiki/Chain_of_trust
+            //
+            // Basic constraints is an X.509 extension type that defines
+            // whether a given certificate is allowed to sign additional
+            // certificates and what path length restrictions may exist.
+            // We use this to judge whether the certificate is an end
+            // certificate or a CA certificate.
+            // https://cryptography.io/en/latest/x509/reference/
+            if (clientCertificateChain[0].getBasicConstraints() != -1) {
+                throw new IllegalArgumentException(
+                        "First certificate in the chain must be a client end certificate");
             }
+
+            for (int i = 1; i < clientCertificateChain.length; i++) {
+                if (clientCertificateChain[i].getBasicConstraints() == -1) {
+                    throw new IllegalArgumentException(
+                            "All certificates following the first must be CA certificates");
+                }
+            }
+            newCerts = Arrays.copyOf(clientCertificateChain,
+                    clientCertificateChain.length);
+
             if (privateKey == null) {
                 throw new IllegalArgumentException("Client cert without a private key");
             }
@@ -755,7 +809,7 @@
         }
 
         mClientPrivateKey = privateKey;
-        mClientCertificate = clientCertificate;
+        mClientCertificateChain = newCerts;
     }
 
     /**
@@ -764,7 +818,24 @@
      * @return X.509 client certificate
      */
     public X509Certificate getClientCertificate() {
-        return mClientCertificate;
+        if (mClientCertificateChain != null && mClientCertificateChain.length > 0) {
+            return mClientCertificateChain[0];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Get the complete client certificate chain
+     *
+     * @return X.509 client certificates
+     */
+    @Nullable public X509Certificate[] getClientCertificateChain() {
+        if (mClientCertificateChain != null && mClientCertificateChain.length > 0) {
+            return mClientCertificateChain;
+        } else {
+            return null;
+        }
     }
 
     /**
@@ -772,7 +843,7 @@
      */
     public void resetClientKeyEntry() {
         mClientPrivateKey = null;
-        mClientCertificate = null;
+        mClientCertificateChain = null;
     }
 
     /**
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 3b6e76f..ab725e2 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -120,11 +120,7 @@
     public static final String PASSPOINT_ICON_RECEIVED_ACTION =
             "android.net.wifi.PASSPOINT_ICON_RECEIVED";
     /** @hide */
-    public static final String EXTRA_PASSPOINT_ICON_BSSID = "bssid";
-    /** @hide */
     public static final String EXTRA_PASSPOINT_ICON_FILE = "file";
-    /** @hide */
-    public static final String EXTRA_PASSPOINT_ICON_DATA = "icon";
 
     /**
      * Broadcast intent action indicating that the a Passpoint release
@@ -159,6 +155,127 @@
     public static final String EXTRA_PASSPOINT_WNM_DELAY = "delay";
 
     /**
+     * Broadcast intent action indicating that a Passpoint provider icon has been received.
+     *
+     * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE
+     */
+    public static final String ACTION_PASSPOINT_ICON =
+            "android.net.wifi.action.PASSPOINT_ICON";
+    /**
+     * BSSID of the sender.
+     *
+     * Type: long
+     */
+    public static final String EXTRA_PASSPOINT_ICON_BSSID =
+            "android.net.wifi.extra.PASSPOINT_ICON_BSSID";
+    /**
+     * Filename of the icon.
+     *
+     * Type: String
+     */
+    public static final String EXTRA_PASSPOINT_ICON_FILENAME =
+            "android.net.wifi.extra.PASSPOINT_ICON_FILENAME";
+    /**
+     * Binary blob of the icon.
+     *
+     * Type: byte[]
+     */
+    public static final String EXTRA_PASSPOINT_ICON_DATA =
+            "android.net.wifi.extra.PASSPOINT_ICON_DATA";
+
+    /**
+     * Broadcast intent action indicating a Passpoint OSU Providers List element has been received.
+     *
+     * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE
+     */
+    public static final String ACTION_PASSPOINT_OSU_PROVIDERS_LIST =
+            "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST";
+    /**
+     * BSSID of the sender.
+     *
+     * Type: long
+     */
+    public static final String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_BSSID =
+            "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_BSSID";
+    /**
+     * Raw data of OSU Providers List ANQP element.  Refer to Section 4.8 of Hotspot 2.0 Release 2
+     * Technical Specification for the exact data format.
+     *
+     * Type: byte[]
+     */
+    public static final String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_DATA =
+            "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_DATA";
+
+    /**
+     * Broadcast intent action indicating that a Passpoint Deauth Imminent frame has been received.
+     *
+     * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE
+     */
+    public static final String ACTION_PASSPOINT_DEAUTH_IMMINENT =
+            "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT";
+    /**
+     * The BSSID of the sender.
+     *
+     * Type: long
+     */
+    public static final String EXTRA_PASSPOINT_DEAUTH_IMMINENT_BSSID =
+            "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_BSSID";
+    /**
+     * Flag indicating failure at BSS (Basic Service Set) or ESS (Extended Service Set) level.
+     *
+     * Type: boolean
+     */
+    public static final String EXTRA_PASSPOINT_DEAUTH_IMMINENT_ESS =
+            "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_ESS";
+    /**
+     * Delay in seconds that a device shall wait before attempting re-association to the same BSS
+     * or ESS (as indicated by {@link #EXTRA_PASSPOINT_DEAUTH_IMMINENT_ESS}.
+     *
+     * Type: int
+     */
+    public static final String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY =
+            "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY";
+    /**
+     * URL that provides a webpage explaining the deauth reason.
+     *
+     * Type: String
+     */
+    public static final String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REASON_URL =
+            "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REASON_URL";
+
+    /**
+     * Broadcast intent action indicating a Passpoint subscription remediation frame has been
+     * received.
+     *
+     * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE
+     */
+    public static final String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION =
+            "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION";
+    /**
+     * The BSSID of the sender.
+     *
+     * Type: long
+     */
+    public static final String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID =
+            "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID";
+    /**
+     * The protocol supported by the subscription remediation server. The possible values are:
+     * 0 - OMA DM
+     * 1 - SOAP XML SPP
+     *
+     * Type: int
+     */
+    public static final String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD =
+            "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD";
+    /**
+     * URL of the subscription remediation server.
+     *
+     * Type: String
+     */
+    public static final String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL =
+            "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL";
+
+    /**
      * Broadcast intent action indicating that Wi-Fi has been enabled, disabled,
      * enabling, disabling, or unknown. One extra provides this state as an int.
      * Another extra provides the previous state, if available.
@@ -898,10 +1015,10 @@
     }
 
     /**
-     * Query for a Hotspot 2.0 release 2 OSU icon
+     * Query for a Hotspot 2.0 release 2 OSU icon file.
+     *
      * @param bssid The BSSID of the AP
-     * @param fileName Icon file name
-     * @hide
+     * @param fileName File name of the icon to query
      */
     public void queryPasspointIcon(long bssid, String fileName) {
         try {
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index 643753a..ca4d121 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -18,9 +18,19 @@
 
 import android.net.wifi.hotspot2.pps.Credential;
 import android.net.wifi.hotspot2.pps.HomeSP;
+import android.net.wifi.hotspot2.pps.Policy;
+import android.net.wifi.hotspot2.pps.UpdateParameter;
 import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.Log;
 import android.os.Parcel;
 
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * Class representing Passpoint configuration.  This contains configurations specified in
  * PerProviderSubscription (PPS) Management Object (MO) tree.
@@ -28,13 +38,108 @@
  * For more info, refer to Hotspot 2.0 PPS MO defined in section 9.1 of the Hotspot 2.0
  * Release 2 Technical Specification.
  *
- * Currently, only HomeSP and Credential subtrees are supported.
- *
  * @hide
  */
 public final class PasspointConfiguration implements Parcelable {
+    private static final String TAG = "PasspointConfiguration";
+
+    /**
+     * Number of bytes for certificate SHA-256 fingerprint byte array.
+     */
+    private static final int CERTIFICATE_SHA256_BYTES = 32;
+
+    /**
+     * Maximum bytes for URL string.
+     */
+    private static final int MAX_URL_BYTES = 1023;
+
+    /**
+     * Integer value used for indicating null value in the Parcel.
+     */
+    private static final int NULL_VALUE = -1;
+
     public HomeSP homeSp = null;
     public Credential credential = null;
+    public Policy policy = null;
+
+    /**
+     * Meta data for performing subscription update.
+     */
+    public UpdateParameter subscriptionUpdate = null;
+
+    /**
+     * List of HTTPS URL for retrieving trust root certificate and the corresponding SHA-256
+     * fingerprint of the certificate.  The certificates are used for verifying AAA server's
+     * identity during EAP authentication.
+     */
+    public Map<String, byte[]> trustRootCertList = null;
+
+    /**
+     * Set by the subscription server, updated every time the configuration is updated by
+     * the subscription server.
+     *
+     * Use Integer.MIN_VALUE to indicate unset value.
+     */
+    public int updateIdentifier = Integer.MIN_VALUE;
+
+    /**
+     * The priority of the credential.
+     *
+     * Use Integer.MIN_VALUE to indicate unset value.
+     */
+    public int credentialPriority = Integer.MIN_VALUE;
+
+    /**
+     * The time this subscription is created. It is in the format of number
+     * of milliseconds since January 1, 1970, 00:00:00 GMT.
+     *
+     * Use Long.MIN_VALUE to indicate unset value.
+     */
+    public long subscriptionCreationTimeInMs = Long.MIN_VALUE;
+
+    /**
+     * The time this subscription will expire. It is in the format of number
+     * of milliseconds since January 1, 1970, 00:00:00 GMT.
+     *
+     * Use Long.MIN_VALUE to indicate unset value.
+     */
+    public long subscriptionExpirationTimeInMs = Long.MIN_VALUE;
+
+    /**
+     * The type of the subscription.  This is defined by the provider and the value is provider
+     * specific.
+     */
+    public String subscriptionType = null;
+
+    /**
+     * The time period for usage statistics accumulation. A value of zero means that usage
+     * statistics are not accumulated on a periodic basis (e.g., a one-time limit for
+     * “pay as you go” - PAYG service). A non-zero value specifies the usage interval in minutes.
+     */
+    public long usageLimitUsageTimePeriodInMinutes = Long.MIN_VALUE;
+
+    /**
+     * The time at which usage statistic accumulation  begins.  It is in the format of number
+     * of milliseconds since January 1, 1970, 00:00:00 GMT.
+     *
+     * Use Long.MIN_VALUE to indicate unset value.
+     */
+    public long usageLimitStartTimeInMs = Long.MIN_VALUE;
+
+    /**
+     * The cumulative data limit in megabytes for the {@link #usageLimitUsageTimePeriodInMinutes}.
+     * A value of zero indicate unlimited data usage.
+     *
+     * Use Long.MIN_VALUE to indicate unset value.
+     */
+    public long usageLimitDataLimit = Long.MIN_VALUE;
+
+    /**
+     * The cumulative time limit in minutes for the {@link #usageLimitUsageTimePeriodInMinutes}.
+     * A value of zero indicate unlimited time usage.
+     */
+    public long usageLimitTimeLimitInMinutes = Long.MIN_VALUE;
+
 
     /**
      * Constructor for creating PasspointConfiguration with default values.
@@ -47,14 +152,34 @@
      * @param source The source to copy from
      */
     public PasspointConfiguration(PasspointConfiguration source) {
-        if (source != null) {
-            if (source.homeSp != null) {
-                homeSp = new HomeSP(source.homeSp);
-            }
-            if (source.credential != null) {
-                credential = new Credential(source.credential);
-            }
+        if (source == null) {
+            return;
         }
+
+        if (source.homeSp != null) {
+            homeSp = new HomeSP(source.homeSp);
+        }
+        if (source.credential != null) {
+            credential = new Credential(source.credential);
+        }
+        if (source.policy != null) {
+            policy = new Policy(source.policy);
+        }
+        if (source.trustRootCertList != null) {
+            trustRootCertList = Collections.unmodifiableMap(source.trustRootCertList);
+        }
+        if (source.subscriptionUpdate != null) {
+            subscriptionUpdate = new UpdateParameter(source.subscriptionUpdate);
+        }
+        updateIdentifier = source.updateIdentifier;
+        credentialPriority = source.credentialPriority;
+        subscriptionCreationTimeInMs = source.subscriptionCreationTimeInMs;
+        subscriptionExpirationTimeInMs = source.subscriptionExpirationTimeInMs;
+        subscriptionType = source.subscriptionType;
+        usageLimitDataLimit = source.usageLimitDataLimit;
+        usageLimitStartTimeInMs = source.usageLimitStartTimeInMs;
+        usageLimitTimeLimitInMinutes = source.usageLimitTimeLimitInMinutes;
+        usageLimitUsageTimePeriodInMinutes = source.usageLimitUsageTimePeriodInMinutes;
     }
 
     @Override
@@ -66,6 +191,18 @@
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeParcelable(homeSp, flags);
         dest.writeParcelable(credential, flags);
+        dest.writeParcelable(policy, flags);
+        dest.writeParcelable(subscriptionUpdate, flags);
+        writeTrustRootCerts(dest, trustRootCertList);
+        dest.writeInt(updateIdentifier);
+        dest.writeInt(credentialPriority);
+        dest.writeLong(subscriptionCreationTimeInMs);
+        dest.writeLong(subscriptionExpirationTimeInMs);
+        dest.writeString(subscriptionType);
+        dest.writeLong(usageLimitUsageTimePeriodInMinutes);
+        dest.writeLong(usageLimitStartTimeInMs);
+        dest.writeLong(usageLimitDataLimit);
+        dest.writeLong(usageLimitTimeLimitInMinutes);
     }
 
     @Override
@@ -77,9 +214,22 @@
             return false;
         }
         PasspointConfiguration that = (PasspointConfiguration) thatObject;
-        return (homeSp == null ? that.homeSp == null : homeSp.equals(that.homeSp)) &&
-                (credential == null ? that.credential == null :
-                    credential.equals(that.credential));
+        return (homeSp == null ? that.homeSp == null : homeSp.equals(that.homeSp))
+                && (credential == null ? that.credential == null
+                        : credential.equals(that.credential))
+                && (policy == null) ? that.policy == null : policy.equals(that.policy)
+                && (subscriptionUpdate == null) ? that.subscriptionUpdate == null
+                        : subscriptionUpdate.equals(that.subscriptionUpdate)
+                && isTrustRootCertListEquals(trustRootCertList, that.trustRootCertList)
+                && updateIdentifier == that.updateIdentifier
+                && credentialPriority == that.credentialPriority
+                && subscriptionCreationTimeInMs == that.subscriptionCreationTimeInMs
+                && subscriptionExpirationTimeInMs == that.subscriptionExpirationTimeInMs
+                && TextUtils.equals(subscriptionType, that.subscriptionType)
+                && usageLimitUsageTimePeriodInMinutes == that.usageLimitUsageTimePeriodInMinutes
+                && usageLimitStartTimeInMs == that.usageLimitStartTimeInMs
+                && usageLimitDataLimit == that.usageLimitDataLimit
+                && usageLimitTimeLimitInMinutes == that .usageLimitTimeLimitInMinutes;
     }
 
     /**
@@ -94,6 +244,37 @@
         if (credential == null || !credential.validate()) {
             return false;
         }
+        if (policy != null && !policy.validate()) {
+            return false;
+        }
+        if (subscriptionUpdate != null && !subscriptionUpdate.validate()) {
+            return false;
+        }
+        if (trustRootCertList != null) {
+            for (Map.Entry<String, byte[]> entry : trustRootCertList.entrySet()) {
+                String url = entry.getKey();
+                byte[] certFingerprint = entry.getValue();
+                if (TextUtils.isEmpty(url)) {
+                    Log.d(TAG, "Empty URL");
+                    return false;
+                }
+                if (url.getBytes(StandardCharsets.UTF_8).length > MAX_URL_BYTES) {
+                    Log.d(TAG, "URL bytes exceeded the max: "
+                            + url.getBytes(StandardCharsets.UTF_8).length);
+                    return false;
+                }
+
+                if (certFingerprint == null) {
+                    Log.d(TAG, "Fingerprint not specified");
+                    return false;
+                }
+                if (certFingerprint.length != CERTIFICATE_SHA256_BYTES) {
+                    Log.d(TAG, "Incorrect size of trust root certificate SHA-256 fingerprint: "
+                            + certFingerprint.length);
+                    return false;
+                }
+            }
+        }
         return true;
     }
 
@@ -104,11 +285,88 @@
                 PasspointConfiguration config = new PasspointConfiguration();
                 config.homeSp = in.readParcelable(null);
                 config.credential = in.readParcelable(null);
+                config.policy = in.readParcelable(null);
+                config.subscriptionUpdate = in.readParcelable(null);
+                config.trustRootCertList = readTrustRootCerts(in);
+                config.updateIdentifier = in.readInt();
+                config.credentialPriority = in.readInt();
+                config.subscriptionCreationTimeInMs = in.readLong();
+                config.subscriptionExpirationTimeInMs = in.readLong();
+                config.subscriptionType = in.readString();
+                config.usageLimitUsageTimePeriodInMinutes = in.readLong();
+                config.usageLimitStartTimeInMs = in.readLong();
+                config.usageLimitDataLimit = in.readLong();
+                config.usageLimitTimeLimitInMinutes = in.readLong();
                 return config;
             }
+
             @Override
             public PasspointConfiguration[] newArray(int size) {
                 return new PasspointConfiguration[size];
             }
+
+            /**
+             * Helper function for reading trust root certificate info list from a Parcel.
+             *
+             * @param in The Parcel to read from
+             * @return The list of trust root certificate URL with the corresponding certificate
+             *         fingerprint
+             */
+            private Map<String, byte[]> readTrustRootCerts(Parcel in) {
+                int size = in.readInt();
+                if (size == NULL_VALUE) {
+                    return null;
+                }
+                Map<String, byte[]> trustRootCerts = new HashMap<>(size);
+                for (int i = 0; i < size; i++) {
+                    String key = in.readString();
+                    byte[] value = in.createByteArray();
+                    trustRootCerts.put(key, value);
+                }
+                return trustRootCerts;
+            }
         };
+
+    /**
+     * Helper function for writing trust root certificate information list.
+     *
+     * @param dest The Parcel to write to
+     * @param trustRootCerts The list of trust root certificate URL with the corresponding
+     *                       certificate fingerprint
+     */
+    private static void writeTrustRootCerts(Parcel dest, Map<String, byte[]> trustRootCerts) {
+        if (trustRootCerts == null) {
+            dest.writeInt(NULL_VALUE);
+            return;
+        }
+        dest.writeInt(trustRootCerts.size());
+        for (Map.Entry<String, byte[]> entry : trustRootCerts.entrySet()) {
+            dest.writeString(entry.getKey());
+            dest.writeByteArray(entry.getValue());
+        }
+    }
+
+    /**
+     * Helper function for comparing two trust root certificate list.  Cannot use Map#equals
+     * method since the value type (byte[]) doesn't override equals method.
+     *
+     * @param list1 The first trust root certificate list
+     * @param list2 The second trust root certificate list
+     * @return true if the two list are equal
+     */
+    private static boolean isTrustRootCertListEquals(Map<String, byte[]> list1,
+            Map<String, byte[]> list2) {
+        if (list1 == null || list2 == null) {
+            return list1 == list2;
+        }
+        if (list1.size() != list2.size()) {
+            return false;
+        }
+        for (Map.Entry<String, byte[]> entry : list1.entrySet()) {
+            if (!Arrays.equals(entry.getValue(), list2.get(entry.getKey()))) {
+                return false;
+            }
+        }
+        return true;
+    }
 }
diff --git a/wifi/java/android/net/wifi/hotspot2/omadm/PPSMOParser.java b/wifi/java/android/net/wifi/hotspot2/omadm/PPSMOParser.java
index 98fd0f3..22b0f97 100644
--- a/wifi/java/android/net/wifi/hotspot2/omadm/PPSMOParser.java
+++ b/wifi/java/android/net/wifi/hotspot2/omadm/PPSMOParser.java
@@ -19,6 +19,8 @@
 import android.net.wifi.hotspot2.PasspointConfiguration;
 import android.net.wifi.hotspot2.pps.Credential;
 import android.net.wifi.hotspot2.pps.HomeSP;
+import android.net.wifi.hotspot2.pps.Policy;
+import android.net.wifi.hotspot2.pps.UpdateParameter;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
@@ -131,6 +133,20 @@
     private static final String NODE_PER_PROVIDER_SUBSCRIPTION = "PerProviderSubscription";
 
     /**
+     * Fields under PerProviderSubscription.
+     */
+    private static final String NODE_UPDATE_IDENTIFIER = "UpdateIdentifier";
+    private static final String NODE_AAA_SERVER_TRUST_ROOT = "AAAServerTrustRoot";
+    private static final String NODE_SUBSCRIPTION_UPDATE = "SubscriptionUpdate";
+    private static final String NODE_SUBSCRIPTION_PARAMETER = "SubscriptionParameter";
+    private static final String NODE_TYPE_OF_SUBSCRIPTION = "TypeOfSubscription";
+    private static final String NODE_USAGE_LIMITS = "UsageLimits";
+    private static final String NODE_DATA_LIMIT = "DataLimit";
+    private static final String NODE_START_DATE = "StartDate";
+    private static final String NODE_TIME_LIMIT = "TimeLimit";
+    private static final String NODE_USAGE_TIME_PERIOD = "UsageTimePeriod";
+    private static final String NODE_CREDENTIAL_PRIORITY = "CredentialPriority";
+    /**
      * Fields under HomeSP subtree.
      */
     private static final String NODE_HOMESP = "HomeSP";
@@ -168,13 +184,40 @@
     private static final String NODE_INNER_METHOD = "InnerMethod";
     private static final String NODE_DIGITAL_CERTIFICATE = "DigitalCertificate";
     private static final String NODE_CERTIFICATE_TYPE = "CertificateType";
-    private static final String NODE_CERT_SHA256_FINGERPRINT = "CertSHA256FingerPrint";
+    private static final String NODE_CERT_SHA256_FINGERPRINT = "CertSHA256Fingerprint";
     private static final String NODE_REALM = "Realm";
     private static final String NODE_SIM = "SIM";
     private static final String NODE_SIM_IMSI = "IMSI";
     private static final String NODE_CHECK_AAA_SERVER_CERT_STATUS = "CheckAAAServerCertStatus";
 
     /**
+     * Fields under Policy subtree.
+     */
+    private static final String NODE_POLICY = "Policy";
+    private static final String NODE_PREFERRED_ROAMING_PARTNER_LIST =
+            "PreferredRoamingPartnerList";
+    private static final String NODE_FQDN_MATCH = "FQDN_Match";
+    private static final String NODE_PRIORITY = "Priority";
+    private static final String NODE_COUNTRY = "Country";
+    private static final String NODE_MIN_BACKHAUL_THRESHOLD = "MinBackhaulThreshold";
+    private static final String NODE_NETWORK_TYPE = "NetworkType";
+    private static final String NODE_DOWNLINK_BANDWIDTH = "DLBandwidth";
+    private static final String NODE_UPLINK_BANDWIDTH = "ULBandwidth";
+    private static final String NODE_POLICY_UPDATE = "PolicyUpdate";
+    private static final String NODE_UPDATE_INTERVAL = "UpdateInterval";
+    private static final String NODE_UPDATE_METHOD = "UpdateMethod";
+    private static final String NODE_RESTRICTION = "Restriction";
+    private static final String NODE_URI = "URI";
+    private static final String NODE_TRUST_ROOT = "TrustRoot";
+    private static final String NODE_CERT_URL = "CertURL";
+    private static final String NODE_SP_EXCLUSION_LIST = "SPExclusionList";
+    private static final String NODE_REQUIRED_PROTO_PORT_TUPLE = "RequiredProtoPortTuple";
+    private static final String NODE_IP_PROTOCOL = "IPProtocol";
+    private static final String NODE_PORT_NUMBER = "PortNumber";
+    private static final String NODE_MAXIMUM_BSS_LOAD_VALUE = "MaximumBSSLoadValue";
+    private static final String NODE_OTHER = "Other";
+
+    /**
      * URN (Unique Resource Name) for PerProviderSubscription Management Object Tree.
      */
     private static final String PPS_MO_URN =
@@ -349,6 +392,10 @@
      *     ...
      *   </RTPProperties>
      *   <Node>
+     *     <NodeName>UpdateIdentifier</NodeName>
+     *     <Value>...</Value>
+     *   </Node>
+     *   <Node>
      *     ...
      *   </Node>
      * </Node>
@@ -361,11 +408,12 @@
             throws ParsingException {
         PasspointConfiguration config = null;
         String nodeName = null;
+        int updateIdentifier = Integer.MIN_VALUE;
         for (XMLNode child : node.getChildren()) {
             switch (child.getTag()) {
                 case TAG_NODE_NAME:
                     if (nodeName != null) {
-                        throw new ParsingException("Duplicant NodeName: " + child.getText());
+                        throw new ParsingException("Duplicate NodeName: " + child.getText());
                     }
                     nodeName = child.getText();
                     if (!TextUtils.equals(nodeName, NODE_PER_PROVIDER_SUBSCRIPTION)) {
@@ -373,13 +421,22 @@
                     }
                     break;
                 case TAG_NODE:
-                    // Only one PerProviderSubscription instance is expected and allowed.
-                    if (config != null) {
-                        throw new ParsingException("Multiple PPS instance");
+                    // A node can be either an UpdateIdentifier node or a PerProviderSubscription
+                    // instance node.  Flatten out the XML tree first by converting it to a PPS
+                    // tree to reduce the complexity of the parsing code.
+                    PPSNode ppsNodeRoot = buildPpsNode(child);
+                    if (TextUtils.equals(ppsNodeRoot.getName(), NODE_UPDATE_IDENTIFIER)) {
+                        if (updateIdentifier != Integer.MIN_VALUE) {
+                            throw new ParsingException("Multiple node for UpdateIdentifier");
+                        }
+                        updateIdentifier = parseInteger(getPpsNodeValue(ppsNodeRoot));
+                    } else {
+                        // Only one PerProviderSubscription instance is expected and allowed.
+                        if (config != null) {
+                            throw new ParsingException("Multiple PPS instance");
+                        }
+                        config = parsePpsInstance(ppsNodeRoot);
                     }
-                    // Convert the XML tree to a PPS tree.
-                    PPSNode ppsInstanceRoot = buildPpsNode(child);
-                    config = parsePpsInstance(ppsInstanceRoot);
                     break;
                 case TAG_RT_PROPERTIES:
                     // Parse and verify URN stored in the RT (Run Time) Properties.
@@ -392,6 +449,9 @@
                     throw new ParsingException("Unknown tag under PPS node: " + child.getTag());
             }
         }
+        if (config != null && updateIdentifier != Integer.MIN_VALUE) {
+            config.updateIdentifier = updateIdentifier;
+        }
         return config;
     }
 
@@ -551,6 +611,21 @@
                 case NODE_CREDENTIAL:
                     config.credential = parseCredential(child);
                     break;
+                case NODE_POLICY:
+                    config.policy = parsePolicy(child);
+                    break;
+                case NODE_AAA_SERVER_TRUST_ROOT:
+                    config.trustRootCertList = parseAAAServerTrustRootList(child);
+                    break;
+                case NODE_SUBSCRIPTION_UPDATE:
+                    config.subscriptionUpdate = parseUpdateParameter(child);
+                    break;
+                case NODE_SUBSCRIPTION_PARAMETER:
+                    parseSubscriptionParameter(child, config);
+                    break;
+                case NODE_CREDENTIAL_PRIORITY:
+                    config.credentialPriority = parseInteger(getPpsNodeValue(child));
+                    break;
                 default:
                     throw new ParsingException("Unknown node: " + child.getName());
             }
@@ -616,11 +691,7 @@
         String[] oiStrArray = oiStr.split(",");
         long[] oiArray = new long[oiStrArray.length];
         for (int i = 0; i < oiStrArray.length; i++) {
-            try {
-                oiArray[i] = Long.parseLong(oiStrArray[i], 16);
-            } catch (NumberFormatException e) {
-                throw new ParsingException("Invalid OI: " + oiStrArray[i]);
-            }
+            oiArray[i] = parseLong(oiStrArray[i], 16);
         }
         return oiArray;
     }
@@ -671,11 +742,7 @@
                     ssid = getPpsNodeValue(child);
                     break;
                 case NODE_HESSID:
-                    try {
-                        hessid = Long.parseLong(getPpsNodeValue(child), 16);
-                    } catch (NumberFormatException e) {
-                        throw new ParsingException("Invalid HESSID: " + getPpsNodeValue(child));
-                    }
+                    hessid = parseLong(getPpsNodeValue(child), 16);
                     break;
                 default:
                     throw new ParsingException("Unknown node under NetworkID instance: " +
@@ -999,6 +1066,503 @@
     }
 
     /**
+     * Parse configurations under PerProviderSubscription/Policy subtree.
+     *
+     * @param node PPSNode representing the root of the PerProviderSubscription/Policy subtree
+     * @return {@link Policy}
+     * @throws ParsingException
+     */
+    private static Policy parsePolicy(PPSNode node) throws ParsingException {
+        if (node.isLeaf()) {
+            throw new ParsingException("Leaf node not expected for Policy");
+        }
+
+        Policy policy = new Policy();
+        for (PPSNode child : node.getChildren()) {
+            switch (child.getName()) {
+                case NODE_PREFERRED_ROAMING_PARTNER_LIST:
+                    policy.preferredRoamingPartnerList = parsePreferredRoamingPartnerList(child);
+                    break;
+                case NODE_MIN_BACKHAUL_THRESHOLD:
+                    parseMinBackhaulThreshold(child, policy);
+                    break;
+                case NODE_POLICY_UPDATE:
+                    policy.policyUpdate = parseUpdateParameter(child);
+                    break;
+                case NODE_SP_EXCLUSION_LIST:
+                    policy.excludedSsidList = parseSpExclusionList(child);
+                    break;
+                case NODE_REQUIRED_PROTO_PORT_TUPLE:
+                    policy.requiredProtoPortMap = parseRequiredProtoPortTuple(child);
+                    break;
+                case NODE_MAXIMUM_BSS_LOAD_VALUE:
+                    policy.maximumBssLoadValue = parseInteger(getPpsNodeValue(child));
+                    break;
+                default:
+                    throw new ParsingException("Unknown node under Policy: " + child.getName());
+            }
+        }
+        return policy;
+    }
+
+    /**
+     * Parse configurations under PerProviderSubscription/Policy/PreferredRoamingPartnerList
+     * subtree.
+     *
+     * @param node PPSNode representing the root of the
+     *             PerProviderSubscription/Policy/PreferredRoamingPartnerList subtree
+     * @return List of {@link Policy#RoamingPartner}
+     * @throws ParsingException
+     */
+    private static List<Policy.RoamingPartner> parsePreferredRoamingPartnerList(PPSNode node)
+            throws ParsingException {
+        if (node.isLeaf()) {
+            throw new ParsingException("Leaf node not expected for PreferredRoamingPartnerList");
+        }
+        List<Policy.RoamingPartner> partnerList = new ArrayList<>();
+        for (PPSNode child : node.getChildren()) {
+            partnerList.add(parsePreferredRoamingPartner(child));
+        }
+        return partnerList;
+    }
+
+    /**
+     * Parse configurations under PerProviderSubscription/Policy/PreferredRoamingPartnerList/<X+>
+     * subtree.
+     *
+     * @param node PPSNode representing the root of the
+     *             PerProviderSubscription/Policy/PreferredRoamingPartnerList/<X+> subtree
+     * @return {@link Policy#RoamingPartner}
+     * @throws ParsingException
+     */
+    private static Policy.RoamingPartner parsePreferredRoamingPartner(PPSNode node)
+            throws ParsingException {
+        if (node.isLeaf()) {
+            throw new ParsingException("Leaf node not expected for PreferredRoamingPartner "
+                    + "instance");
+        }
+
+        Policy.RoamingPartner roamingPartner = new Policy.RoamingPartner();
+        for (PPSNode child : node.getChildren()) {
+            switch (child.getName()) {
+                case NODE_FQDN_MATCH:
+                    // FQDN_Match field is in the format of "[FQDN],[MatchInfo]", where [MatchInfo]
+                    // is either "exactMatch" for exact match of FQDN or "includeSubdomains" for
+                    // matching all FQDNs with the same sub-domain.
+                    String fqdnMatch = getPpsNodeValue(child);
+                    String[] fqdnMatchArray = fqdnMatch.split(",");
+                    if (fqdnMatchArray.length != 2) {
+                        throw new ParsingException("Invalid FQDN_Match: " + fqdnMatch);
+                    }
+                    roamingPartner.fqdn = fqdnMatchArray[0];
+                    if (TextUtils.equals(fqdnMatchArray[1], "exactMatch")) {
+                        roamingPartner.fqdnExactMatch = true;
+                    } else if (TextUtils.equals(fqdnMatchArray[1], "includeSubdomains")) {
+                        roamingPartner.fqdnExactMatch = false;
+                    } else {
+                        throw new ParsingException("Invalid FQDN_Match: " + fqdnMatch);
+                    }
+                    break;
+                case NODE_PRIORITY:
+                    roamingPartner.priority = parseInteger(getPpsNodeValue(child));
+                    break;
+                case NODE_COUNTRY:
+                    roamingPartner.countries = getPpsNodeValue(child);
+                    break;
+                default:
+                    throw new ParsingException("Unknown node under PreferredRoamingPartnerList "
+                            + "instance " + child.getName());
+            }
+        }
+        return roamingPartner;
+    }
+
+    /**
+     * Parse configurations under PerProviderSubscription/Policy/MinBackhaulThreshold subtree
+     * into the given policy.
+     *
+     * @param node PPSNode representing the root of the
+     *             PerProviderSubscription/Policy/MinBackhaulThreshold subtree
+     * @param policy The policy to store the MinBackhualThreshold configuration
+     * @throws ParsingException
+     */
+    private static void parseMinBackhaulThreshold(PPSNode node, Policy policy)
+            throws ParsingException {
+        if (node.isLeaf()) {
+            throw new ParsingException("Leaf node not expected for MinBackhaulThreshold");
+        }
+        for (PPSNode child : node.getChildren()) {
+            parseMinBackhaulThresholdInstance(child, policy);
+        }
+    }
+
+    /**
+     * Parse configurations under PerProviderSubscription/Policy/MinBackhaulThreshold/<X+> subtree
+     * into the given policy.
+     *
+     * @param node PPSNode representing the root of the
+     *             PerProviderSubscription/Policy/MinBackhaulThreshold/<X+> subtree
+     * @param policy The policy to store the MinBackhaulThreshold configuration
+     * @throws ParsingException
+     */
+    private static void parseMinBackhaulThresholdInstance(PPSNode node, Policy policy)
+            throws ParsingException {
+        if (node.isLeaf()) {
+            throw new ParsingException("Leaf node not expected for MinBackhaulThreshold instance");
+        }
+        String networkType = null;
+        long downlinkBandwidth = Long.MIN_VALUE;
+        long uplinkBandwidth = Long.MIN_VALUE;
+        for (PPSNode child : node.getChildren()) {
+            switch (child.getName()) {
+                case NODE_NETWORK_TYPE:
+                    networkType = getPpsNodeValue(child);
+                    break;
+                case NODE_DOWNLINK_BANDWIDTH:
+                    downlinkBandwidth = parseLong(getPpsNodeValue(child), 10);
+                    break;
+                case NODE_UPLINK_BANDWIDTH:
+                    uplinkBandwidth = parseLong(getPpsNodeValue(child), 10);
+                    break;
+                default:
+                    throw new ParsingException("Unknown node under MinBackhaulThreshold instance "
+                            + child.getName());
+            }
+        }
+        if (networkType == null) {
+            throw new ParsingException("Missing NetworkType field");
+        }
+
+        if (TextUtils.equals(networkType, "home")) {
+            policy.minHomeDownlinkBandwidth = downlinkBandwidth;
+            policy.minHomeUplinkBandwidth = uplinkBandwidth;
+        } else if (TextUtils.equals(networkType, "roaming")) {
+            policy.minRoamingDownlinkBandwidth = downlinkBandwidth;
+            policy.minRoamingUplinkBandwidth = uplinkBandwidth;
+        } else {
+            throw new ParsingException("Invalid network type: " + networkType);
+        }
+    }
+
+    /**
+     * Parse update parameters. This contained configurations from either
+     * PerProviderSubscription/Policy/PolicyUpdate or PerProviderSubscription/SubscriptionUpdate
+     * subtree.
+     *
+     * @param node PPSNode representing the root of the PerProviderSubscription/Policy/PolicyUpdate
+     *             or PerProviderSubscription/SubscriptionUpdate subtree
+     * @return {@link UpdateParameter}
+     * @throws ParsingException
+     */
+    private static UpdateParameter parseUpdateParameter(PPSNode node)
+            throws ParsingException {
+        if (node.isLeaf()) {
+            throw new ParsingException("Leaf node not expected for Update Parameters");
+        }
+
+        UpdateParameter updateParam = new UpdateParameter();
+        for (PPSNode child : node.getChildren()) {
+            switch(child.getName()) {
+                case NODE_UPDATE_INTERVAL:
+                    updateParam.updateIntervalInMinutes = parseLong(getPpsNodeValue(child), 10);
+                    break;
+                case NODE_UPDATE_METHOD:
+                    updateParam.updateMethod = getPpsNodeValue(child);
+                    break;
+                case NODE_RESTRICTION:
+                    updateParam.restriction = getPpsNodeValue(child);
+                    break;
+                case NODE_URI:
+                    updateParam.serverUri = getPpsNodeValue(child);
+                    break;
+                case NODE_USERNAME_PASSWORD:
+                    Pair<String, String> usernamePassword = parseUpdateUserCredential(child);
+                    updateParam.username = usernamePassword.first;
+                    updateParam.base64EncodedPassword = usernamePassword.second;
+                    break;
+                case NODE_TRUST_ROOT:
+                    Pair<String, byte[]> trustRoot = parseTrustRoot(child);
+                    updateParam.trustRootCertUrl = trustRoot.first;
+                    updateParam.trustRootCertSha256Fingerprint = trustRoot.second;
+                    break;
+                case NODE_OTHER:
+                    Log.d(TAG, "Ignore unsupported paramter: " + child.getName());
+                    break;
+                default:
+                    throw new ParsingException("Unknown node under Update Parameters: "
+                            + child.getName());
+            }
+        }
+        return updateParam;
+    }
+
+    /**
+     * Parse username and password parameters associated with policy or subscription update.
+     * This contained configurations under either
+     * PerProviderSubscription/Policy/PolicyUpdate/UsernamePassword or
+     * PerProviderSubscription/SubscriptionUpdate/UsernamePassword subtree.
+     *
+     * @param node PPSNode representing the root of the UsernamePassword subtree
+     * @return Pair of username and password
+     * @throws ParsingException
+     */
+    private static Pair<String, String> parseUpdateUserCredential(PPSNode node)
+            throws ParsingException {
+        if (node.isLeaf()) {
+            throw new ParsingException("Leaf node not expected for UsernamePassword");
+        }
+
+        String username = null;
+        String password = null;
+        for (PPSNode child : node.getChildren()) {
+            switch (child.getName()) {
+                case NODE_USERNAME:
+                    username = getPpsNodeValue(child);
+                    break;
+                case NODE_PASSWORD:
+                    password = getPpsNodeValue(child);
+                    break;
+                default:
+                    throw new ParsingException("Unknown node under UsernamePassword: "
+                            + child.getName());
+            }
+        }
+        return Pair.create(username, password);
+    }
+
+    /**
+     * Parse the trust root parameters associated with policy update, subscription update, or AAA
+     * server trust root.
+     *
+     * This contained configurations under either
+     * PerProviderSubscription/Policy/PolicyUpdate/TrustRoot or
+     * PerProviderSubscription/SubscriptionUpdate/TrustRoot or
+     * PerProviderSubscription/AAAServerTrustRoot/<X+> subtree.
+     *
+     * @param node PPSNode representing the root of the TrustRoot subtree
+     * @return Pair of Certificate URL and fingerprint
+     * @throws ParsingException
+     */
+    private static Pair<String, byte[]> parseTrustRoot(PPSNode node)
+            throws ParsingException {
+        if (node.isLeaf()) {
+            throw new ParsingException("Leaf node not expected for TrustRoot");
+        }
+
+        String certUrl = null;
+        byte[] certFingerprint = null;
+        for (PPSNode child : node.getChildren()) {
+            switch (child.getName()) {
+                case NODE_CERT_URL:
+                    certUrl = getPpsNodeValue(child);
+                    break;
+                case NODE_CERT_SHA256_FINGERPRINT:
+                    certFingerprint = parseHexString(getPpsNodeValue(child));
+                    break;
+                default:
+                    throw new ParsingException("Unknown node under TrustRoot: "
+                            + child.getName());
+            }
+        }
+        return Pair.create(certUrl, certFingerprint);
+    }
+
+    /**
+     * Parse configurations under PerProviderSubscription/Policy/SPExclusionList subtree.
+     *
+     * @param node PPSNode representing the root of the
+     *             PerProviderSubscription/Policy/SPExclusionList subtree
+     * @return Array of excluded SSIDs
+     * @throws ParsingException
+     */
+    private static String[] parseSpExclusionList(PPSNode node) throws ParsingException {
+        if (node.isLeaf()) {
+            throw new ParsingException("Leaf node not expected for SPExclusionList");
+        }
+        List<String> ssidList = new ArrayList<>();
+        for (PPSNode child : node.getChildren()) {
+            ssidList.add(parseSpExclusionInstance(child));
+        }
+        return ssidList.toArray(new String[ssidList.size()]);
+    }
+
+    /**
+     * Parse configurations under PerProviderSubscription/Policy/SPExclusionList/<X+> subtree.
+     *
+     * @param node PPSNode representing the root of the
+     *             PerProviderSubscription/Policy/SPExclusionList/<X+> subtree
+     * @return String
+     * @throws ParsingException
+     */
+    private static String parseSpExclusionInstance(PPSNode node) throws ParsingException {
+        if (node.isLeaf()) {
+            throw new ParsingException("Leaf node not expected for SPExclusion instance");
+        }
+        String ssid = null;
+        for (PPSNode child : node.getChildren()) {
+            switch (child.getName()) {
+                case NODE_SSID:
+                    ssid = getPpsNodeValue(child);
+                    break;
+                default:
+                    throw new ParsingException("Unknown node under SPExclusion instance");
+            }
+        }
+        return ssid;
+    }
+
+    /**
+     * Parse configurations under PerProviderSubscription/Policy/RequiredProtoPortTuple subtree.
+     *
+     * @param node PPSNode representing the root of the
+     *             PerProviderSubscription/Policy/RequiredProtoPortTuple subtree
+     * @return Map of IP Protocol to Port Number tuples
+     * @throws ParsingException
+     */
+    private static Map<Integer, String> parseRequiredProtoPortTuple(PPSNode node)
+            throws ParsingException {
+        if (node.isLeaf()) {
+            throw new ParsingException("Leaf node not expected for RequiredProtoPortTuple");
+        }
+        Map<Integer, String> protoPortTupleMap = new HashMap<>();
+        for (PPSNode child : node.getChildren()) {
+            Pair<Integer, String> protoPortTuple = parseProtoPortTuple(child);
+            protoPortTupleMap.put(protoPortTuple.first, protoPortTuple.second);
+        }
+        return protoPortTupleMap;
+    }
+
+    /**
+     * Parse configurations under PerProviderSubscription/Policy/RequiredProtoPortTuple/<X+>
+     * subtree.
+     *
+     * @param node PPSNode representing the root of the
+     *             PerProviderSubscription/Policy/RequiredProtoPortTuple/<X+> subtree
+     * @return Pair of IP Protocol to Port Number tuple
+     * @throws ParsingException
+     */
+    private static Pair<Integer, String> parseProtoPortTuple(PPSNode node)
+            throws ParsingException {
+        if (node.isLeaf()) {
+            throw new ParsingException("Leaf node not expected for RequiredProtoPortTuple "
+                    + "instance");
+        }
+        int proto = Integer.MIN_VALUE;
+        String ports = null;
+        for (PPSNode child : node.getChildren()) {
+            switch (child.getName()) {
+                case NODE_IP_PROTOCOL:
+                    proto = parseInteger(getPpsNodeValue(child));
+                    break;
+                case NODE_PORT_NUMBER:
+                    ports = getPpsNodeValue(child);
+                    break;
+                default:
+                    throw new ParsingException("Unknown node under RequiredProtoPortTuple instance"
+                            + child.getName());
+            }
+        }
+        if (proto == Integer.MIN_VALUE) {
+            throw new ParsingException("Missing IPProtocol field");
+        }
+        if (ports == null) {
+            throw new ParsingException("Missing PortNumber field");
+        }
+        return Pair.create(proto, ports);
+    }
+
+    /**
+     * Parse configurations under PerProviderSubscription/AAAServerTrustRoot subtree.
+     *
+     * @param node PPSNode representing the root of PerProviderSubscription/AAAServerTrustRoot
+     *             subtree
+     * @return Map of certificate URL with the corresponding certificate fingerprint
+     * @throws ParsingException
+     */
+    private static Map<String, byte[]> parseAAAServerTrustRootList(PPSNode node)
+            throws ParsingException {
+        if (node.isLeaf()) {
+            throw new ParsingException("Leaf node not expected for AAAServerTrustRoot");
+        }
+        Map<String, byte[]> certList = new HashMap<>();
+        for (PPSNode child : node.getChildren()) {
+            Pair<String, byte[]> certTuple = parseTrustRoot(child);
+            certList.put(certTuple.first, certTuple.second);
+        }
+        return certList;
+    }
+
+    /**
+     * Parse configurations under PerProviderSubscription/SubscriptionParameter subtree.
+     *
+     * @param node PPSNode representing the root of PerProviderSubscription/SubscriptionParameter
+     *             subtree
+     * @param config Instance of {@link PasspointConfiguration}
+     * @throws ParsingException
+     */
+    private static void parseSubscriptionParameter(PPSNode node, PasspointConfiguration config)
+            throws ParsingException {
+        if (node.isLeaf()) {
+            throw new ParsingException("Leaf node not expected for SubscriptionParameter");
+        }
+        for (PPSNode child : node.getChildren()) {
+            switch (child.getName()) {
+                case NODE_CREATION_DATE:
+                    config.subscriptionCreationTimeInMs = parseDate(getPpsNodeValue(child));
+                    break;
+                case NODE_EXPIRATION_DATE:
+                    config.subscriptionExpirationTimeInMs = parseDate(getPpsNodeValue(child));
+                    break;
+                case NODE_TYPE_OF_SUBSCRIPTION:
+                    config.subscriptionType = getPpsNodeValue(child);
+                    break;
+                case NODE_USAGE_LIMITS:
+                    parseUsageLimits(child, config);
+                    break;
+                default:
+                    throw new ParsingException("Unknown node under SubscriptionParameter"
+                            + child.getName());
+            }
+        }
+    }
+
+    /**
+     * Parse configurations under PerProviderSubscription/SubscriptionParameter/UsageLimits
+     * subtree.
+     *
+     * @param node PPSNode representing the root of
+     *             PerProviderSubscription/SubscriptionParameter/UsageLimits subtree
+     * @param config Instance of {@link PasspointConfiguration}
+     * @throws ParsingException
+     */
+    private static void parseUsageLimits(PPSNode node, PasspointConfiguration config)
+            throws ParsingException {
+        if (node.isLeaf()) {
+            throw new ParsingException("Leaf node not expected for UsageLimits");
+        }
+        for (PPSNode child : node.getChildren()) {
+            switch (child.getName()) {
+                case NODE_DATA_LIMIT:
+                    config.usageLimitDataLimit = parseLong(getPpsNodeValue(child), 10);
+                    break;
+                case NODE_START_DATE:
+                    config.usageLimitStartTimeInMs = parseDate(getPpsNodeValue(child));
+                    break;
+                case NODE_TIME_LIMIT:
+                    config.usageLimitTimeLimitInMinutes = parseLong(getPpsNodeValue(child), 10);
+                    break;
+                case NODE_USAGE_TIME_PERIOD:
+                    config.usageLimitUsageTimePeriodInMinutes =
+                            parseLong(getPpsNodeValue(child), 10);
+                    break;
+                default:
+                    throw new ParsingException("Unknown node under UsageLimits"
+                            + child.getName());
+            }
+        }
+    }
+
+    /**
      * Convert a hex string to a byte array.
      *
      * @param str String containing hex values
@@ -1054,6 +1618,21 @@
     }
 
     /**
+     * Parse a string representing a long integer.
+     *
+     * @param value String of long integer value
+     * @return long
+     * @throws ParsingException
+     */
+    private static long parseLong(String value, int radix) throws ParsingException {
+        try {
+            return Long.parseLong(value, radix);
+        } catch (NumberFormatException e) {
+            throw new ParsingException("Invalid long integer value: " + value);
+        }
+    }
+
+    /**
      * Convert a List<Long> to a primitive long array long[].
      *
      * @param list List to be converted
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Policy.aidl b/wifi/java/android/net/wifi/hotspot2/pps/Policy.aidl
new file mode 100644
index 0000000..e923f1f
--- /dev/null
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Policy.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.wifi.hotspot2.pps;
+
+parcelable Policy;
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
new file mode 100644
index 0000000..b2583d3
--- /dev/null
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
@@ -0,0 +1,452 @@
+/**
+ * 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.wifi.hotspot2.pps;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Class representing Policy subtree in PerProviderSubscription (PPS)
+ * Management Object (MO) tree.
+ *
+ * The Policy specifies additional criteria for Passpoint network selections, such as preferred
+ * roaming partner, minimum backhaul bandwidth, and etc. It also provides the meta data for
+ * updating the policy.
+ *
+ * For more info, refer to Hotspot 2.0 PPS MO defined in section 9.1 of the Hotspot 2.0
+ * Release 2 Technical Specification.
+ *
+ * @hide
+ */
+public final class Policy implements Parcelable {
+    private static final String TAG = "Policy";
+
+    /**
+     * Default priority for preferred roaming partner.
+     */
+    public static final int PREFERRED_ROAMING_PARTNER_DEFAULT_PRIORITY = 128;
+
+    /**
+     * Maximum number of SSIDs in the exclusion list.
+     */
+    private static final int MAX_EXCLUSION_SSIDS = 128;
+
+    /**
+     * Maximum byte for SSID.
+     */
+    private static final int MAX_SSID_BYTES = 32;
+
+    /**
+     * Maximum bytes for port string in {@link #requiredProtoPortMap}.
+     */
+    private static final int MAX_PORT_STRING_BYTES = 64;
+
+    /**
+     * Integer value used for indicating null value in the Parcel.
+     */
+    private static final int NULL_VALUE = -1;
+
+    /**
+     * Minimum available downlink/uplink bandwidth (in kilobits per second) required when
+     * selecting a network from home providers.
+     *
+     * The bandwidth is calculated as the LinkSpeed * (1 – LinkLoad/255), where LinkSpeed
+     * and LinkLoad parameters are drawn from the WAN Metrics ANQP element at that hotspot.
+     *
+     * Using Long.MIN_VALUE to indicate unset value.
+     */
+    public long minHomeDownlinkBandwidth = Long.MIN_VALUE;
+    public long minHomeUplinkBandwidth = Long.MIN_VALUE;
+
+    /**
+     * Minimum available downlink/uplink bandwidth (in kilobits per second) required when
+     * selecting a network from roaming providers.
+     *
+     * The bandwidth is calculated as the LinkSpeed * (1 – LinkLoad/255), where LinkSpeed
+     * and LinkLoad parameters are drawn from the WAN Metrics ANQP element at that hotspot.
+     *
+     * Using Long.MIN_VALUE to indicate unset value.
+     */
+    public long minRoamingDownlinkBandwidth = Long.MIN_VALUE;
+    public long minRoamingUplinkBandwidth = Long.MIN_VALUE;
+
+    /**
+     * List of SSIDs that are not preferred by the Home SP.
+     */
+    public String[] excludedSsidList = null;
+
+    /**
+     * List of IP protocol and port number required by one or more operator supported application.
+     * The port string contained one or more port numbers delimited by ",".
+     */
+    public Map<Integer, String> requiredProtoPortMap = null;
+
+    /**
+     * This specifies the maximum acceptable BSS load policy.  This is used to prevent device
+     * from joining an AP whose channel is overly congested with traffic.
+     * Using Integer.MIN_VALUE to indicate unset value.
+     */
+    public int maximumBssLoadValue = Integer.MIN_VALUE;
+
+    /**
+     * Policy associated with a roaming provider.  This specifies a priority associated
+     * with a roaming provider for given list of countries.
+     *
+     * Contains field under PerProviderSubscription/Policy/PreferredRoamingPartnerList.
+     */
+    public static final class RoamingPartner implements Parcelable {
+        /**
+         * FQDN of the roaming partner.
+         */
+        public String fqdn = null;
+
+        /**
+         * Flag indicating the exact match of FQDN is required for FQDN matching.
+         *
+         * When this flag is set to false, sub-domain matching is used.  For example, when
+         * {@link #fqdn} s set to "example.com", "host.example.com" would be a match.
+         */
+        public boolean fqdnExactMatch = false;
+
+        /**
+         * Priority associated with this roaming partner policy.
+         */
+        public int priority = PREFERRED_ROAMING_PARTNER_DEFAULT_PRIORITY;
+
+        /**
+         * A string contained One or more, comma delimited (i.e., ",") ISO/IEC 3166-1 two
+         * character country strings or the country-independent value, "*".
+         */
+        public String countries = null;
+
+        public RoamingPartner() {}
+
+        public RoamingPartner(RoamingPartner source) {
+            if (source != null) {
+                fqdn = source.fqdn;
+                fqdnExactMatch = source.fqdnExactMatch;
+                priority = source.priority;
+                countries = source.countries;
+            }
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeString(fqdn);
+            dest.writeInt(fqdnExactMatch ? 1 : 0);
+            dest.writeInt(priority);
+            dest.writeString(countries);
+        }
+
+        @Override
+        public boolean equals(Object thatObject) {
+            if (this == thatObject) {
+                return true;
+            }
+            if (!(thatObject instanceof RoamingPartner)) {
+                return false;
+            }
+
+            RoamingPartner that = (RoamingPartner) thatObject;
+            return TextUtils.equals(fqdn, that.fqdn)
+                    && fqdnExactMatch == that.fqdnExactMatch
+                    && priority == that.priority
+                    && TextUtils.equals(countries, that.countries);
+        }
+
+        /**
+         * Validate RoamingParnter data.
+         *
+         * @return true on success
+         */
+        public boolean validate() {
+            if (TextUtils.isEmpty(fqdn)) {
+                Log.d(TAG, "Missing FQDN");
+                return false;
+            }
+            if (TextUtils.isEmpty(countries)) {
+                Log.d(TAG, "Missing countries");
+                return false;
+            }
+            return true;
+        }
+
+        public static final Creator<RoamingPartner> CREATOR =
+            new Creator<RoamingPartner>() {
+                @Override
+                public RoamingPartner createFromParcel(Parcel in) {
+                    RoamingPartner roamingPartner = new RoamingPartner();
+                    roamingPartner.fqdn = in.readString();
+                    roamingPartner.fqdnExactMatch = in.readInt() != 0;
+                    roamingPartner.priority = in.readInt();
+                    roamingPartner.countries = in.readString();
+                    return roamingPartner;
+                }
+
+                @Override
+                public RoamingPartner[] newArray(int size) {
+                    return new RoamingPartner[size];
+                }
+            };
+    }
+    public List<RoamingPartner> preferredRoamingPartnerList = null;
+
+    /**
+     * Meta data used for policy update.
+     */
+    public UpdateParameter policyUpdate = null;
+
+    /**
+     * Constructor for creating Policy with default values.
+     */
+    public Policy() {}
+
+    /**
+     * Copy constructor.
+     *
+     * @param source The source to copy from
+     */
+    public Policy(Policy source) {
+        if (source == null) {
+            return;
+        }
+        minHomeDownlinkBandwidth = source.minHomeDownlinkBandwidth;
+        minHomeUplinkBandwidth = source.minHomeUplinkBandwidth;
+        minRoamingDownlinkBandwidth = source.minRoamingDownlinkBandwidth;
+        minRoamingUplinkBandwidth = source.minRoamingUplinkBandwidth;
+        maximumBssLoadValue = source.maximumBssLoadValue;
+        if (source.excludedSsidList != null) {
+            excludedSsidList = Arrays.copyOf(source.excludedSsidList,
+                    source.excludedSsidList.length);
+        }
+        if (source.requiredProtoPortMap != null) {
+            requiredProtoPortMap = Collections.unmodifiableMap(source.requiredProtoPortMap);
+        }
+        if (source.preferredRoamingPartnerList != null) {
+            preferredRoamingPartnerList = Collections.unmodifiableList(
+                    source.preferredRoamingPartnerList);
+        }
+        if (source.policyUpdate != null) {
+            policyUpdate = new UpdateParameter(source.policyUpdate);
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeLong(minHomeDownlinkBandwidth);
+        dest.writeLong(minHomeUplinkBandwidth);
+        dest.writeLong(minRoamingDownlinkBandwidth);
+        dest.writeLong(minRoamingUplinkBandwidth);
+        dest.writeStringArray(excludedSsidList);
+        writeProtoPortMap(dest, requiredProtoPortMap);
+        dest.writeInt(maximumBssLoadValue);
+        writeRoamingPartnerList(dest, flags, preferredRoamingPartnerList);
+        dest.writeParcelable(policyUpdate, flags);
+    }
+
+    @Override
+    public boolean equals(Object thatObject) {
+        if (this == thatObject) {
+            return true;
+        }
+        if (!(thatObject instanceof Policy)) {
+            return false;
+        }
+        Policy that = (Policy) thatObject;
+
+        return minHomeDownlinkBandwidth == that.minHomeDownlinkBandwidth
+                && minHomeUplinkBandwidth == that.minHomeUplinkBandwidth
+                && minRoamingDownlinkBandwidth == that.minRoamingDownlinkBandwidth
+                && minRoamingUplinkBandwidth == that.minRoamingUplinkBandwidth
+                && Arrays.equals(excludedSsidList, that.excludedSsidList)
+                && (requiredProtoPortMap == null) ? that.requiredProtoPortMap == null
+                        : requiredProtoPortMap.equals(that.requiredProtoPortMap)
+                && maximumBssLoadValue == that.maximumBssLoadValue
+                && (preferredRoamingPartnerList == null) ? that.preferredRoamingPartnerList == null
+                        : preferredRoamingPartnerList.equals(that.preferredRoamingPartnerList)
+                && (policyUpdate == null) ? that.policyUpdate == null
+                        : policyUpdate.equals(that.policyUpdate);
+    }
+
+    /**
+     * Validate Policy data.
+     *
+     * @return true on success
+     */
+    public boolean validate() {
+        if (policyUpdate == null) {
+            Log.d(TAG, "PolicyUpdate not specified");
+            return false;
+        }
+        if (!policyUpdate.validate()) {
+            return false;
+        }
+
+        // Validate SSID exclusion list.
+        if (excludedSsidList != null) {
+            if (excludedSsidList.length > MAX_EXCLUSION_SSIDS) {
+                Log.d(TAG, "SSID exclusion list size exceeded the max: "
+                        + excludedSsidList.length);
+                return false;
+            }
+            for (String ssid : excludedSsidList) {
+                if (ssid.getBytes(StandardCharsets.UTF_8).length > MAX_SSID_BYTES) {
+                    Log.d(TAG, "Invalid SSID: " + ssid);
+                    return false;
+                }
+            }
+        }
+        // Validate required protocol to port map.
+        if (requiredProtoPortMap != null) {
+            for (Map.Entry<Integer, String> entry : requiredProtoPortMap.entrySet()) {
+                String portNumber = entry.getValue();
+                if (portNumber.getBytes(StandardCharsets.UTF_8).length > MAX_PORT_STRING_BYTES) {
+                    Log.d(TAG, "PortNumber string bytes exceeded the max: " + portNumber);
+                    return false;
+                }
+            }
+        }
+        // Validate preferred roaming partner list.
+        if (preferredRoamingPartnerList != null) {
+            for (RoamingPartner partner : preferredRoamingPartnerList) {
+                if (!partner.validate()) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    public static final Creator<Policy> CREATOR =
+        new Creator<Policy>() {
+            @Override
+            public Policy createFromParcel(Parcel in) {
+                Policy policy = new Policy();
+                policy.minHomeDownlinkBandwidth = in.readLong();
+                policy.minHomeUplinkBandwidth = in.readLong();
+                policy.minRoamingDownlinkBandwidth = in.readLong();
+                policy.minRoamingUplinkBandwidth = in.readLong();
+                policy.excludedSsidList = in.createStringArray();
+                policy.requiredProtoPortMap = readProtoPortMap(in);
+                policy.maximumBssLoadValue = in.readInt();
+                policy.preferredRoamingPartnerList = readRoamingPartnerList(in);
+                policy.policyUpdate = in.readParcelable(null);
+                return policy;
+            }
+
+            @Override
+            public Policy[] newArray(int size) {
+                return new Policy[size];
+            }
+
+            /**
+             * Helper function for reading IP Protocol to Port Number map from a Parcel.
+             *
+             * @param in The Parcel to read from
+             * @return Map of IP protocol to port number
+             */
+            private Map<Integer, String> readProtoPortMap(Parcel in) {
+                int size = in.readInt();
+                if (size == NULL_VALUE) {
+                    return null;
+                }
+                Map<Integer, String> protoPortMap = new HashMap<>(size);
+                for (int i = 0; i < size; i++) {
+                    int key = in.readInt();
+                    String value = in.readString();
+                    protoPortMap.put(key, value);
+                }
+                return protoPortMap;
+            }
+
+            /**
+             * Helper function for reading roaming partner list from a Parcel.
+             *
+             * @param in The Parcel to read from
+             * @return List of roaming partners
+             */
+            private List<RoamingPartner> readRoamingPartnerList(Parcel in) {
+                int size = in.readInt();
+                if (size == NULL_VALUE) {
+                    return null;
+                }
+                List<RoamingPartner> partnerList = new ArrayList<>();
+                for (int i = 0; i < size; i++) {
+                    partnerList.add(in.readParcelable(null));
+                }
+                return partnerList;
+            }
+
+        };
+
+    /**
+     * Helper function for writing IP Protocol to Port Number map to a Parcel.
+     *
+     * @param dest The Parcel to write to
+     * @param protoPortMap The map to write
+     */
+    private static void writeProtoPortMap(Parcel dest, Map<Integer, String> protoPortMap) {
+        if (protoPortMap == null) {
+            dest.writeInt(NULL_VALUE);
+            return;
+        }
+        dest.writeInt(protoPortMap.size());
+        for (Map.Entry<Integer, String> entry : protoPortMap.entrySet()) {
+            dest.writeInt(entry.getKey());
+            dest.writeString(entry.getValue());
+        }
+    }
+
+    /**
+     * Helper function for writing roaming partner list to a Parcel.
+     *
+     * @param dest The Parcel to write to
+     * @param flags The flag about how the object should be written
+     * @param partnerList The partner list to write
+     */
+    private static void writeRoamingPartnerList(Parcel dest, int flags,
+            List<RoamingPartner> partnerList) {
+        if (partnerList == null) {
+            dest.writeInt(NULL_VALUE);
+            return;
+        }
+        dest.writeInt(partnerList.size());
+        for (RoamingPartner partner : partnerList) {
+            dest.writeParcelable(partner, flags);
+        }
+    }
+}
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.aidl b/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.aidl
new file mode 100644
index 0000000..701db47
--- /dev/null
+++ b/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.wifi.hotspot2.pps;
+
+parcelable UpdateParameter;
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java b/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java
new file mode 100644
index 0000000..a390df7
--- /dev/null
+++ b/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java
@@ -0,0 +1,303 @@
+/**
+ * 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.wifi.hotspot2.pps;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.Base64;
+import android.util.Log;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+
+/**
+ * Class representing configuration parameters for subscription or policy update in
+ * PerProviderSubscription (PPS) Management Object (MO) tree.  This is used by both
+ * PerProviderSubscription/Policy/PolicyUpdate and PerProviderSubscription/SubscriptionUpdate
+ * subtree.
+ *
+ * For more info, refer to Hotspot 2.0 PPS MO defined in section 9.1 of the Hotspot 2.0
+ * Release 2 Technical Specification.
+ *
+ * @hide
+ */
+public final class UpdateParameter implements Parcelable {
+    private static final String TAG = "UpdateParameter";
+
+    /**
+     * Value indicating policy update is not applicable.  Thus, never check with policy server
+     * for updates.
+     */
+    public static final long UPDATE_CHECK_INTERVAL_NEVER = 0xFFFFFFFFL;
+
+    /**
+     * Valid string for UpdateMethod.
+     */
+    public static final String UPDATE_METHOD_OMADM = "OMA-DM-ClientInitiated";
+    public static final String UPDATE_METHOD_SSP = "SSP-ClientInitiated";
+
+    /**
+     * Valid string for Restriction.
+     */
+    public static final String UPDATE_RESTRICTION_HOMESP = "HomeSP";
+    public static final String UPDATE_RESTRICTION_ROAMING_PARTNER = "RoamingPartner";
+    public static final String UPDATE_RESTRICTION_UNRESTRICTED = "Unrestricted";
+
+    /**
+     * Maximum bytes for URI string.
+     */
+    private static final int MAX_URI_BYTES = 1023;
+
+    /**
+     * Maximum bytes for URI string.
+     */
+    private static final int MAX_URL_BYTES = 1023;
+
+    /**
+     * Maximum bytes for username.
+     */
+    private static final int MAX_USERNAME_BYTES = 63;
+
+    /**
+     * Maximum bytes for password.
+     */
+    private static final int MAX_PASSWORD_BYTES = 255;
+
+    /**
+     * Number of bytes for certificate SHA-256 fingerprint byte array.
+     */
+    private static final int CERTIFICATE_SHA256_BYTES = 32;
+
+    /**
+     * This specifies how often the mobile device shall check with policy server for updates.
+     *
+     * Using Long.MIN_VALUE to indicate unset value.
+     */
+    public long updateIntervalInMinutes = Long.MIN_VALUE;
+
+    /**
+     * The method used to update the policy.  Permitted values are "OMA-DM-ClientInitiated"
+     * and "SPP-ClientInitiated".
+     */
+    public String updateMethod = null;
+
+    /**
+     * This specifies the hotspots at which the subscription update is permitted.  Permitted
+     * values are "HomeSP", "RoamingPartner", or "Unrestricted";
+     */
+    public String restriction = null;
+
+    /**
+     * The URI of the update server.
+     */
+    public String serverUri = null;
+
+    /**
+     * Username used to authenticate with the policy server.
+     */
+    public String username = null;
+
+    /**
+     * Base64 encoded password used to authenticate with the policy server.
+     */
+    public String base64EncodedPassword = null;
+
+    /**
+     * HTTPS URL for retrieving certificate for trust root.  The trust root is used to validate
+     * policy server's identity.
+     */
+    public String trustRootCertUrl = null;
+
+    /**
+     * SHA-256 fingerprint of the certificate located at {@link #trustRootCertUrl}
+     */
+    public byte[] trustRootCertSha256Fingerprint = null;
+
+    /**
+     * Constructor for creating Policy with default values.
+     */
+    public UpdateParameter() {}
+
+    /**
+     * Copy constructor.
+     *
+     * @param source The source to copy from
+     */
+    public UpdateParameter(UpdateParameter source) {
+        if (source == null) {
+            return;
+        }
+        updateIntervalInMinutes = source.updateIntervalInMinutes;
+        updateMethod = source.updateMethod;
+        restriction = source.restriction;
+        serverUri = source.serverUri;
+        username = source.username;
+        base64EncodedPassword = source.base64EncodedPassword;
+        trustRootCertUrl = source.trustRootCertUrl;
+        if (source.trustRootCertSha256Fingerprint != null) {
+            trustRootCertSha256Fingerprint = Arrays.copyOf(source.trustRootCertSha256Fingerprint,
+                    source.trustRootCertSha256Fingerprint.length);
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeLong(updateIntervalInMinutes);
+        dest.writeString(updateMethod);
+        dest.writeString(restriction);
+        dest.writeString(serverUri);
+        dest.writeString(username);
+        dest.writeString(base64EncodedPassword);
+        dest.writeString(trustRootCertUrl);
+        dest.writeByteArray(trustRootCertSha256Fingerprint);
+    }
+
+    @Override
+    public boolean equals(Object thatObject) {
+        if (this == thatObject) {
+            return true;
+        }
+        if (!(thatObject instanceof UpdateParameter)) {
+            return false;
+        }
+        UpdateParameter that = (UpdateParameter) thatObject;
+
+        return updateIntervalInMinutes == that.updateIntervalInMinutes
+                && TextUtils.equals(updateMethod, that.updateMethod)
+                && TextUtils.equals(restriction, that.restriction)
+                && TextUtils.equals(serverUri, that.serverUri)
+                && TextUtils.equals(username, that.username)
+                && TextUtils.equals(base64EncodedPassword, that.base64EncodedPassword)
+                && TextUtils.equals(trustRootCertUrl, that.trustRootCertUrl)
+                && Arrays.equals(trustRootCertSha256Fingerprint,
+                        that.trustRootCertSha256Fingerprint);
+    }
+
+    /**
+     * Validate UpdateParameter data.
+     *
+     * @return true on success
+     */
+    public boolean validate() {
+        if (updateIntervalInMinutes == Long.MIN_VALUE) {
+            Log.d(TAG, "Update interval not specified");
+            return false;
+        }
+        // Update not applicable.
+        if (updateIntervalInMinutes == UPDATE_CHECK_INTERVAL_NEVER) {
+            return true;
+        }
+
+        if (!TextUtils.equals(updateMethod, UPDATE_METHOD_OMADM)
+                && !TextUtils.equals(updateMethod, UPDATE_METHOD_SSP)) {
+            Log.d(TAG, "Unknown update method: " + updateMethod);
+            return false;
+        }
+
+        if (!TextUtils.equals(restriction, UPDATE_RESTRICTION_HOMESP)
+                && !TextUtils.equals(restriction, UPDATE_RESTRICTION_ROAMING_PARTNER)
+                && !TextUtils.equals(restriction, UPDATE_RESTRICTION_UNRESTRICTED)) {
+            Log.d(TAG, "Unknown restriction: " + restriction);
+            return false;
+        }
+
+        if (TextUtils.isEmpty(serverUri)) {
+            Log.d(TAG, "Missing update server URI");
+            return false;
+        }
+        if (serverUri.getBytes(StandardCharsets.UTF_8).length > MAX_URI_BYTES) {
+            Log.d(TAG, "URI bytes exceeded the max: "
+                    + serverUri.getBytes(StandardCharsets.UTF_8).length);
+            return false;
+        }
+
+        if (TextUtils.isEmpty(username)) {
+            Log.d(TAG, "Missing username");
+            return false;
+        }
+        if (username.getBytes(StandardCharsets.UTF_8).length > MAX_USERNAME_BYTES) {
+            Log.d(TAG, "Username bytes exceeded the max: "
+                    + username.getBytes(StandardCharsets.UTF_8).length);
+            return false;
+        }
+
+        if (TextUtils.isEmpty(base64EncodedPassword)) {
+            Log.d(TAG, "Missing username");
+            return false;
+        }
+        if (base64EncodedPassword.getBytes(StandardCharsets.UTF_8).length > MAX_PASSWORD_BYTES) {
+            Log.d(TAG, "Password bytes exceeded the max: "
+                    + base64EncodedPassword.getBytes(StandardCharsets.UTF_8).length);
+            return false;
+        }
+        try {
+            Base64.decode(base64EncodedPassword, Base64.DEFAULT);
+        } catch (IllegalArgumentException e) {
+            Log.d(TAG, "Invalid encoding for password: " + base64EncodedPassword);
+            return false;
+        }
+
+        if (TextUtils.isEmpty(trustRootCertUrl)) {
+            Log.d(TAG, "Missing trust root certificate URL");
+            return false;
+        }
+        if (trustRootCertUrl.getBytes(StandardCharsets.UTF_8).length > MAX_URL_BYTES) {
+            Log.d(TAG, "Trust root cert URL bytes exceeded the max: "
+                    + trustRootCertUrl.getBytes(StandardCharsets.UTF_8).length);
+            return false;
+        }
+
+        if (trustRootCertSha256Fingerprint == null) {
+            Log.d(TAG, "Missing trust root certificate SHA-256 fingerprint");
+            return false;
+        }
+        if (trustRootCertSha256Fingerprint.length != CERTIFICATE_SHA256_BYTES) {
+            Log.d(TAG, "Incorrect size of trust root certificate SHA-256 fingerprint: "
+                    + trustRootCertSha256Fingerprint.length);
+            return false;
+        }
+        return true;
+    }
+
+    public static final Creator<UpdateParameter> CREATOR =
+        new Creator<UpdateParameter>() {
+            @Override
+            public UpdateParameter createFromParcel(Parcel in) {
+                UpdateParameter updateParam = new UpdateParameter();
+                updateParam.updateIntervalInMinutes = in.readLong();
+                updateParam.updateMethod = in.readString();
+                updateParam.restriction = in.readString();
+                updateParam.serverUri = in.readString();
+                updateParam.username = in.readString();
+                updateParam.base64EncodedPassword = in.readString();
+                updateParam.trustRootCertUrl = in.readString();
+                updateParam.trustRootCertSha256Fingerprint = in.createByteArray();
+                return updateParam;
+            }
+
+            @Override
+            public UpdateParameter[] newArray(int size) {
+                return new UpdateParameter[size];
+            }
+        };
+}
diff --git a/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.base64 b/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.base64
index 8c1eb08..995963d 100644
--- a/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.base64
+++ b/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.base64
@@ -42,7 +42,7 @@
 a05sY25ScFptbGpZWFJsVkhsd1pUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lX
 eDFaVDU0TlRBNWRqTThMMVpoCmJIVmxQZ29nSUNBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lD
 QWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmwKVG1GdFpUNURaWEowVTBoQk1q
-VTJSbWx1WjJWeVVISnBiblE4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzZFdV
+VTJSbWx1WjJWeWNISnBiblE4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzZFdV
 KwpNV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpG
 bU1XWXhaakZtTVdZeFpqRm1NV1l4ClpqRm1NV1l4Wmp3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0FnSUNB
 OEwwNXZaR1UrQ2lBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWcKSUR4T2IyUmxQZ29nSUNB
diff --git a/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.conf b/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.conf
index 6d86dd5..3ddd09f 100644
--- a/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.conf
+++ b/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.conf
@@ -35,7 +35,7 @@
 aWZpY2F0ZTwvTm9kZU5hbWU+CiAgICAgICAgICA8Tm9kZT4KICAgICAgICAgICAgPE5vZGVOYW1l
 PkNlcnRpZmljYXRlVHlwZTwvTm9kZU5hbWU+CiAgICAgICAgICAgIDxWYWx1ZT54NTA5djM8L1Zh
 bHVlPgogICAgICAgICAgPC9Ob2RlPgogICAgICAgICAgPE5vZGU+CiAgICAgICAgICAgIDxOb2Rl
-TmFtZT5DZXJ0U0hBMjU2RmluZ2VyUHJpbnQ8L05vZGVOYW1lPgogICAgICAgICAgICA8VmFsdWU+
+TmFtZT5DZXJ0U0hBMjU2RmluZ2VycHJpbnQ8L05vZGVOYW1lPgogICAgICAgICAgICA8VmFsdWU+
 MWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYxZjFmMWYx
 ZjFmMWYxZjwvVmFsdWU+CiAgICAgICAgICA8L05vZGU+CiAgICAgICAgPC9Ob2RlPgogICAgICAg
 IDxOb2RlPgogICAgICAgICAgPE5vZGVOYW1lPlNJTTwvTm9kZU5hbWU+CiAgICAgICAgICA8Tm9k
diff --git a/wifi/tests/assets/pps/PerProviderSubscription.xml b/wifi/tests/assets/pps/PerProviderSubscription.xml
index 3969f69..7f2d95d 100644
--- a/wifi/tests/assets/pps/PerProviderSubscription.xml
+++ b/wifi/tests/assets/pps/PerProviderSubscription.xml
@@ -8,6 +8,10 @@
       </Type>
     </RTProperties>
     <Node>
+      <NodeName>UpdateIdentifier</NodeName>
+      <Value>12</Value>
+    </Node>
+    <Node>
       <NodeName>i001</NodeName>
       <Node>
         <NodeName>HomeSP</NodeName>
@@ -143,7 +147,7 @@
             <Value>x509v3</Value>
           </Node>
           <Node>
-            <NodeName>CertSHA256FingerPrint</NodeName>
+            <NodeName>CertSHA256Fingerprint</NodeName>
             <Value>1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f</Value>
           </Node>
         </Node>
@@ -159,6 +163,237 @@
           </Node>
         </Node>
       </Node>
+      <Node>
+        <NodeName>Policy</NodeName>
+        <Node>
+          <NodeName>PreferredRoamingPartnerList</NodeName>
+          <Node>
+            <NodeName>p001</NodeName>
+            <Node>
+              <NodeName>FQDN_Match</NodeName>
+              <Value>test1.fqdn.com,exactMatch</Value>
+            </Node>
+            <Node>
+              <NodeName>Priority</NodeName>
+              <Value>127</Value>
+            </Node>
+            <Node>
+              <NodeName>Country</NodeName>
+              <Value>us,fr</Value>
+            </Node>
+          </Node>
+          <Node>
+            <NodeName>p002</NodeName>
+            <Node>
+              <NodeName>FQDN_Match</NodeName>
+              <Value>test2.fqdn.com,includeSubdomains</Value>
+            </Node>
+            <Node>
+              <NodeName>Priority</NodeName>
+              <Value>200</Value>
+            </Node>
+            <Node>
+              <NodeName>Country</NodeName>
+              <Value>*</Value>
+            </Node>
+          </Node>
+        </Node>
+        <Node>
+          <NodeName>MinBackhaulThreshold</NodeName>
+          <Node>
+            <NodeName>m001</NodeName>
+            <Node>
+              <NodeName>NetworkType</NodeName>
+              <Value>home</Value>
+            </Node>
+            <Node>
+              <NodeName>DLBandwidth</NodeName>
+              <Value>23412</Value>
+            </Node>
+            <Node>
+              <NodeName>ULBandwidth</NodeName>
+              <Value>9823</Value>
+            </Node>
+          </Node>
+          <Node>
+            <NodeName>m002</NodeName>
+            <Node>
+              <NodeName>NetworkType</NodeName>
+              <Value>roaming</Value>
+            </Node>
+            <Node>
+              <NodeName>DLBandwidth</NodeName>
+              <Value>9271</Value>
+            </Node>
+            <Node>
+              <NodeName>ULBandwidth</NodeName>
+              <Value>2315</Value>
+            </Node>
+          </Node>
+        </Node>
+        <Node>
+          <NodeName>PolicyUpdate</NodeName>
+          <Node>
+            <NodeName>UpdateInterval</NodeName>
+            <Value>120</Value>
+          </Node>
+          <Node>
+            <NodeName>UpdateMethod</NodeName>
+            <Value>OMA-DM-ClientInitiated</Value>
+          </Node>
+          <Node>
+            <NodeName>Restriction</NodeName>
+            <Value>HomeSP</Value>
+          </Node>
+          <Node>
+            <NodeName>URI</NodeName>
+            <Value>policy.update.com</Value>
+          </Node>
+          <Node>
+            <NodeName>UsernamePassword</NodeName>
+            <Node>
+              <NodeName>Username</NodeName>
+              <Value>updateUser</Value>
+            </Node>
+            <Node>
+              <NodeName>Password</NodeName>
+              <Value>updatePass</Value>
+            </Node>
+          </Node>
+          <Node>
+            <NodeName>TrustRoot</NodeName>
+            <Node>
+              <NodeName>CertURL</NodeName>
+              <Value>update.cert.com</Value>
+            </Node>
+            <Node>
+              <NodeName>CertSHA256Fingerprint</NodeName>
+              <Value>1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f</Value>
+            </Node>
+          </Node>
+        </Node>
+        <Node>
+          <NodeName>SPExclusionList</NodeName>
+          <Node>
+            <NodeName>s001</NodeName>
+            <Node>
+              <NodeName>SSID</NodeName>
+              <Value>excludeSSID</Value>
+            </Node>
+          </Node>
+        </Node>
+        <Node>
+          <NodeName>RequiredProtoPortTuple</NodeName>
+          <Node>
+            <NodeName>r001</NodeName>
+            <Node>
+              <NodeName>IPProtocol</NodeName>
+              <Value>12</Value>
+            </Node>
+            <Node>
+              <NodeName>PortNumber</NodeName>
+              <Value>34,92,234</Value>
+            </Node>
+          </Node>
+        </Node>
+        <Node>
+          <NodeName>MaximumBSSLoadValue</NodeName>
+          <Value>23</Value>
+        </Node>
+      </Node>
+      <Node>
+        <NodeName>CredentialPriority</NodeName>
+        <Value>99</Value>
+      </Node>
+      <Node>
+        <NodeName>AAAServerTrustRoot</NodeName>
+        <Node>
+          <NodeName>a001</NodeName>
+          <Node>
+            <NodeName>CertURL</NodeName>
+            <Value>server1.trust.root.com</Value>
+          </Node>
+          <Node>
+            <NodeName>CertSHA256Fingerprint</NodeName>
+            <Value>1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f</Value>
+          </Node>
+        </Node>
+      </Node>
+      <Node>
+        <NodeName>SubscriptionUpdate</NodeName>
+        <Node>
+          <NodeName>UpdateInterval</NodeName>
+          <Value>120</Value>
+        </Node>
+        <Node>
+          <NodeName>UpdateMethod</NodeName>
+          <Value>SSP-ClientInitiated</Value>
+        </Node>
+        <Node>
+          <NodeName>Restriction</NodeName>
+          <Value>RoamingPartner</Value>
+        </Node>
+        <Node>
+          <NodeName>URI</NodeName>
+          <Value>subscription.update.com</Value>
+        </Node>
+        <Node>
+          <NodeName>UsernamePassword</NodeName>
+          <Node>
+            <NodeName>Username</NodeName>
+            <Value>subscriptionUser</Value>
+          </Node>
+          <Node>
+            <NodeName>Password</NodeName>
+            <Value>subscriptionPass</Value>
+          </Node>
+        </Node>
+        <Node>
+          <NodeName>TrustRoot</NodeName>
+          <Node>
+            <NodeName>CertURL</NodeName>
+            <Value>subscription.update.cert.com</Value>
+          </Node>
+          <Node>
+            <NodeName>CertSHA256Fingerprint</NodeName>
+            <Value>1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f1f</Value>
+          </Node>
+        </Node>
+      </Node>
+      <Node>
+        <NodeName>SubscriptionParameter</NodeName>
+        <Node>
+          <NodeName>CreationDate</NodeName>
+          <Value>2016-02-01T10:00:00Z</Value>
+        </Node>
+        <Node>
+          <NodeName>ExpirationDate</NodeName>
+          <Value>2016-03-01T10:00:00Z</Value>
+        </Node>
+        <Node>
+          <NodeName>TypeOfSubscription</NodeName>
+          <Value>Gold</Value>
+        </Node>
+        <Node>
+          <NodeName>UsageLimits</NodeName>
+          <Node>
+            <NodeName>DataLimit</NodeName>
+            <Value>921890</Value>
+          </Node>
+          <Node>
+            <NodeName>StartDate</NodeName>
+            <Value>2016-12-01T10:00:00Z</Value>
+          </Node>
+          <Node>
+            <NodeName>TimeLimit</NodeName>
+            <Value>120</Value>
+          </Node>
+          <Node>
+            <NodeName>UsageTimePeriod</NodeName>
+            <Value>99910</Value>
+          </Node>
+        </Node>
+      </Node>
     </Node>
   </Node>
 </MgmtTree>
diff --git a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
index 0e503d5..fa546a5 100644
--- a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
@@ -87,6 +87,52 @@
     }
 
     @Test
+    public void testSetClientKeyEntryWithNull() {
+        mEnterpriseConfig.setClientKeyEntry(null, null);
+        assertEquals(null, mEnterpriseConfig.getClientCertificateChain());
+        assertEquals(null, mEnterpriseConfig.getClientCertificate());
+        mEnterpriseConfig.setClientKeyEntryWithCertificateChain(null, null);
+        assertEquals(null, mEnterpriseConfig.getClientCertificateChain());
+        assertEquals(null, mEnterpriseConfig.getClientCertificate());
+    }
+
+    @Test
+    public void testSetClientCertificateChain() {
+        PrivateKey clientKey = FakeKeys.RSA_KEY1;
+        X509Certificate cert0 = FakeKeys.CLIENT_CERT;
+        X509Certificate cert1 = FakeKeys.CA_CERT1;
+        X509Certificate[] clientChain = new X509Certificate[] {cert0, cert1};
+        mEnterpriseConfig.setClientKeyEntryWithCertificateChain(clientKey, clientChain);
+        X509Certificate[] result = mEnterpriseConfig.getClientCertificateChain();
+        assertEquals(result.length, 2);
+        assertTrue(result[0] == cert0 && result[1] == cert1);
+        assertTrue(mEnterpriseConfig.getClientCertificate() == cert0);
+    }
+
+    private boolean isClientCertificateChainInvalid(X509Certificate[] clientChain) {
+        boolean exceptionThrown = false;
+        try {
+            PrivateKey clientKey = FakeKeys.RSA_KEY1;
+            mEnterpriseConfig.setClientKeyEntryWithCertificateChain(clientKey, clientChain);
+        } catch (IllegalArgumentException e) {
+            exceptionThrown = true;
+        }
+        return exceptionThrown;
+    }
+
+    @Test
+    public void testSetInvalidClientCertificateChain() {
+        X509Certificate clientCert = FakeKeys.CLIENT_CERT;
+        X509Certificate caCert = FakeKeys.CA_CERT1;
+        assertTrue("Invalid client certificate",
+                isClientCertificateChainInvalid(new X509Certificate[] {caCert, caCert}));
+        assertTrue("Invalid CA certificate",
+                isClientCertificateChainInvalid(new X509Certificate[] {clientCert, clientCert}));
+        assertTrue("Both certificates invalid",
+                isClientCertificateChainInvalid(new X509Certificate[] {caCert, clientCert}));
+    }
+
+    @Test
     public void testSaveSingleCaCertificateAlias() {
         final String alias = "single_alias 0";
         mEnterpriseConfig.setCaCertificateAliases(new String[] {alias});
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index 2350d32..1eb08e0 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -22,16 +22,26 @@
 import android.net.wifi.EAPConstants;
 import android.net.wifi.hotspot2.pps.Credential;
 import android.net.wifi.hotspot2.pps.HomeSP;
+import android.net.wifi.hotspot2.pps.Policy;
+import android.net.wifi.hotspot2.pps.UpdateParameter;
 import android.os.Parcel;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Base64;
 
 import org.junit.Test;
 
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+
 /**
  * Unit tests for {@link android.net.wifi.hotspot2.PasspointConfiguration}.
  */
 @SmallTest
 public class PasspointConfigurationTest {
+    private static final int MAX_URL_BYTES = 1023;
+    private static final int CERTIFICATE_FINGERPRINT_BYTES = 32;
 
     /**
      * Utility function for creating a {@link android.net.wifi.hotspot2.pps.HomeSP}.
@@ -66,6 +76,93 @@
     }
 
     /**
+     * Helper function for creating a {@link Policy} for testing.
+     *
+     * @return {@link Policy}
+     */
+    private static Policy createPolicy() {
+        Policy policy = new Policy();
+        policy.minHomeDownlinkBandwidth = 123;
+        policy.minHomeUplinkBandwidth = 345;
+        policy.minRoamingDownlinkBandwidth = 567;
+        policy.minRoamingUplinkBandwidth = 789;
+        policy.maximumBssLoadValue = 12;
+        policy.excludedSsidList = new String[] {"ssid1", "ssid2"};
+        policy.requiredProtoPortMap = new HashMap<>();
+        policy.requiredProtoPortMap.put(12, "23,342,123");
+        policy.requiredProtoPortMap.put(23, "789,372,1235");
+
+        policy.preferredRoamingPartnerList = new ArrayList<>();
+        Policy.RoamingPartner partner1 = new Policy.RoamingPartner();
+        partner1.fqdn = "partner1.com";
+        partner1.fqdnExactMatch = true;
+        partner1.priority = 12;
+        partner1.countries = "us,jp";
+        Policy.RoamingPartner partner2 = new Policy.RoamingPartner();
+        partner2.fqdn = "partner2.com";
+        partner2.fqdnExactMatch = false;
+        partner2.priority = 42;
+        partner2.countries = "ca,fr";
+        policy.preferredRoamingPartnerList.add(partner1);
+        policy.preferredRoamingPartnerList.add(partner2);
+
+        policy.policyUpdate = new UpdateParameter();
+        policy.policyUpdate.updateIntervalInMinutes = 1712;
+        policy.policyUpdate.updateMethod = UpdateParameter.UPDATE_METHOD_OMADM;
+        policy.policyUpdate.restriction = UpdateParameter.UPDATE_RESTRICTION_HOMESP;
+        policy.policyUpdate.serverUri = "policy.update.com";
+        policy.policyUpdate.username = "username";
+        policy.policyUpdate.base64EncodedPassword =
+                Base64.encodeToString("password".getBytes(), Base64.DEFAULT);
+        policy.policyUpdate.trustRootCertUrl = "trust.cert.com";
+        policy.policyUpdate.trustRootCertSha256Fingerprint =
+                new byte[CERTIFICATE_FINGERPRINT_BYTES];
+
+        return policy;
+    }
+
+    private static UpdateParameter createSubscriptionUpdate() {
+        UpdateParameter subUpdate = new UpdateParameter();
+        subUpdate.updateIntervalInMinutes = 9021;
+        subUpdate.updateMethod = UpdateParameter.UPDATE_METHOD_SSP;
+        subUpdate.restriction = UpdateParameter.UPDATE_RESTRICTION_ROAMING_PARTNER;
+        subUpdate.serverUri = "subscription.update.com";
+        subUpdate.username = "subUsername";
+        subUpdate.base64EncodedPassword =
+                Base64.encodeToString("subPassword".getBytes(), Base64.DEFAULT);
+        subUpdate.trustRootCertUrl = "subscription.trust.cert.com";
+        subUpdate.trustRootCertSha256Fingerprint = new byte[CERTIFICATE_FINGERPRINT_BYTES];
+        return subUpdate;
+    }
+    /**
+     * Helper function for creating a {@link PasspointConfiguration} for testing.
+     *
+     * @return {@link PasspointConfiguration}
+     */
+    private static PasspointConfiguration createConfig() {
+        PasspointConfiguration config = new PasspointConfiguration();
+        config.homeSp = createHomeSp();
+        config.credential = createCredential();
+        config.policy = createPolicy();
+        config.subscriptionUpdate = createSubscriptionUpdate();
+        config.trustRootCertList = new HashMap<>();
+        config.trustRootCertList.put("trustRoot.cert1.com",
+                new byte[CERTIFICATE_FINGERPRINT_BYTES]);
+        config.trustRootCertList.put("trustRoot.cert2.com",
+                new byte[CERTIFICATE_FINGERPRINT_BYTES]);
+        config.updateIdentifier = 1;
+        config.credentialPriority = 120;
+        config.subscriptionCreationTimeInMs = 231200;
+        config.subscriptionExpirationTimeInMs = 2134232;
+        config.subscriptionType = "Gold";
+        config.usageLimitUsageTimePeriodInMinutes = 3600;
+        config.usageLimitStartTimeInMs = 124214213;
+        config.usageLimitDataLimit = 14121;
+        config.usageLimitTimeLimitInMinutes = 78912;
+        return config;
+    }
+
+    /**
      * Verify parcel write and read consistency for the given configuration.
      *
      * @param writeConfig The configuration to verify
@@ -92,39 +189,73 @@
     }
 
     /**
-     * Verify parcel read/write for a configuration that contained both HomeSP and Credential.
+     * Verify parcel read/write for a configuration that contained the full configuration.
      *
      * @throws Exception
      */
     @Test
-    public void verifyParcelWithHomeSPAndCredential() throws Exception {
-        PasspointConfiguration config = new PasspointConfiguration();
-        config.homeSp = createHomeSp();
-        config.credential = createCredential();
+    public void verifyParcelWithFullConfiguration() throws Exception {
+        verifyParcel(createConfig());
+    }
+
+    /**
+     * Verify parcel read/write for a configuration that doesn't contain HomeSP.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void verifyParcelWithoutHomeSP() throws Exception {
+        PasspointConfiguration config = createConfig();
+        config.homeSp = null;
         verifyParcel(config);
     }
 
     /**
-     * Verify parcel read/write for a configuration that contained only HomeSP.
+     * Verify parcel read/write for a configuration that doesn't contain Credential.
      *
      * @throws Exception
      */
     @Test
-    public void verifyParcelWithHomeSPOnly() throws Exception {
-        PasspointConfiguration config = new PasspointConfiguration();
-        config.homeSp = createHomeSp();
+    public void verifyParcelWithoutCredential() throws Exception {
+        PasspointConfiguration config = createConfig();
+        config.credential = null;
         verifyParcel(config);
     }
 
     /**
-     * Verify parcel read/write for a configuration that contained only Credential.
+     * Verify parcel read/write for a configuration that doesn't contain Policy.
      *
      * @throws Exception
      */
     @Test
-    public void verifyParcelWithCredentialOnly() throws Exception {
-        PasspointConfiguration config = new PasspointConfiguration();
-        config.credential = createCredential();
+    public void verifyParcelWithoutPolicy() throws Exception {
+        PasspointConfiguration config = createConfig();
+        config.policy = null;
+        verifyParcel(config);
+    }
+
+    /**
+     * Verify parcel read/write for a configuration that doesn't contain subscription update.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void verifyParcelWithoutSubscriptionUpdate() throws Exception {
+        PasspointConfiguration config = createConfig();
+        config.subscriptionUpdate = null;
+        verifyParcel(config);
+    }
+
+    /**
+     * Verify parcel read/write for a configuration that doesn't contain trust root certificate
+     * list.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void verifyParcelWithoutTrustRootCertList() throws Exception {
+        PasspointConfiguration config = createConfig();
+        config.trustRootCertList = null;
         verifyParcel(config);
     }
 
@@ -140,43 +271,108 @@
     }
 
     /**
+     * Verify that a configuration contained all fields is valid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateFullConfig() throws Exception {
+        PasspointConfiguration config = createConfig();
+        assertTrue(config.validate());
+    }
+
+    /**
      * Verify that a configuration without Credential is invalid.
      *
      * @throws Exception
      */
     @Test
     public void validateConfigWithoutCredential() throws Exception {
-        PasspointConfiguration config = new PasspointConfiguration();
-        config.homeSp = createHomeSp();
+        PasspointConfiguration config = createConfig();
+        config.credential = null;
         assertFalse(config.validate());
     }
 
     /**
-     * Verify that a a configuration without HomeSP is invalid.
+     * Verify that a configuration without HomeSP is invalid.
      *
      * @throws Exception
      */
     @Test
     public void validateConfigWithoutHomeSp() throws Exception {
-        PasspointConfiguration config = new PasspointConfiguration();
-        config.credential = createCredential();
+        PasspointConfiguration config = createConfig();
+        config.homeSp = null;
         assertFalse(config.validate());
     }
 
     /**
-     * Verify a valid configuration.
+     * Verify that a configuration without Policy is valid, since Policy configurations
+     * are optional (applied for Hotspot 2.0 Release only).
      *
      * @throws Exception
      */
     @Test
-    public void validateValidConfig() throws Exception {
-        PasspointConfiguration config = new PasspointConfiguration();
-        config.homeSp = createHomeSp();
-        config.credential = createCredential();
+    public void validateConfigWithoutPolicy() throws Exception {
+        PasspointConfiguration config = createConfig();
+        config.policy = null;
         assertTrue(config.validate());
     }
 
     /**
+     * Verify that a configuration without subscription update is valid, since subscription
+     * update configurations are optional (applied for Hotspot 2.0 Release only).
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateConfigWithoutSubscriptionUpdate() throws Exception {
+        PasspointConfiguration config = createConfig();
+        config.subscriptionUpdate = null;
+        assertTrue(config.validate());
+    }
+
+    /**
+     * Verify that a configuration with a trust root certificate URL exceeding the max size
+     * is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateConfigWithInvalidTrustRootCertUrl() throws Exception {
+        PasspointConfiguration config = createConfig();
+        byte[] rawUrlBytes = new byte[MAX_URL_BYTES + 1];
+        Arrays.fill(rawUrlBytes, (byte) 'a');
+        config.trustRootCertList.put(new String(rawUrlBytes, StandardCharsets.UTF_8),
+                new byte[CERTIFICATE_FINGERPRINT_BYTES]);
+        assertFalse(config.validate());
+
+        config.trustRootCertList = new HashMap<>();
+        config.trustRootCertList.put(null, new byte[CERTIFICATE_FINGERPRINT_BYTES]);
+        assertFalse(config.validate());
+    }
+
+    /**
+     * Verify that a configuration with an invalid trust root certificate fingerprint is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateConfigWithInvalidTrustRootCertFingerprint() throws Exception {
+        PasspointConfiguration config = createConfig();
+        config.trustRootCertList = new HashMap<>();
+        config.trustRootCertList.put("test.cert.com", new byte[CERTIFICATE_FINGERPRINT_BYTES + 1]);
+        assertFalse(config.validate());
+
+        config.trustRootCertList = new HashMap<>();
+        config.trustRootCertList.put("test.cert.com", new byte[CERTIFICATE_FINGERPRINT_BYTES - 1]);
+        assertFalse(config.validate());
+
+        config.trustRootCertList = new HashMap<>();
+        config.trustRootCertList.put("test.cert.com", null);
+        assertFalse(config.validate());
+    }
+
+    /**
      * Verify that copy constructor works when pass in a null source.
      *
      * @throws Exception
@@ -195,9 +391,7 @@
      */
     @Test
     public void validateCopyConstructorWithValidSource() throws Exception {
-        PasspointConfiguration sourceConfig = new PasspointConfiguration();
-        sourceConfig.homeSp = createHomeSp();
-        sourceConfig.credential = createCredential();
+        PasspointConfiguration sourceConfig = createConfig();
         PasspointConfiguration copyConfig = new PasspointConfiguration(sourceConfig);
         assertTrue(copyConfig.equals(sourceConfig));
     }
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/omadm/PPSMOParserTest.java b/wifi/tests/src/android/net/wifi/hotspot2/omadm/PPSMOParserTest.java
index 1c7508e..055204c 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/omadm/PPSMOParserTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/omadm/PPSMOParserTest.java
@@ -23,7 +23,10 @@
 import android.net.wifi.hotspot2.PasspointConfiguration;
 import android.net.wifi.hotspot2.pps.Credential;
 import android.net.wifi.hotspot2.pps.HomeSP;
+import android.net.wifi.hotspot2.pps.Policy;
+import android.net.wifi.hotspot2.pps.UpdateParameter;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
 
 import org.junit.Test;
 
@@ -33,6 +36,7 @@
 import java.io.InputStreamReader;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 
@@ -81,7 +85,38 @@
      * @return {@link PasspointConfiguration}
      */
     private PasspointConfiguration generateConfigurationFromPPSMOTree() throws Exception {
+        DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+
         PasspointConfiguration config = new PasspointConfiguration();
+        config.updateIdentifier = 12;
+        config.credentialPriority = 99;
+
+        // AAA Server trust root.
+        config.trustRootCertList = new HashMap<>();
+        byte[] certFingerprint = new byte[32];
+        Arrays.fill(certFingerprint, (byte) 0x1f);
+        config.trustRootCertList.put("server1.trust.root.com", certFingerprint);
+
+        // Subscription update.
+        config.subscriptionUpdate = new UpdateParameter();
+        config.subscriptionUpdate.updateIntervalInMinutes = 120;
+        config.subscriptionUpdate.updateMethod = UpdateParameter.UPDATE_METHOD_SSP;
+        config.subscriptionUpdate.restriction = UpdateParameter.UPDATE_RESTRICTION_ROAMING_PARTNER;
+        config.subscriptionUpdate.serverUri = "subscription.update.com";
+        config.subscriptionUpdate.username = "subscriptionUser";
+        config.subscriptionUpdate.base64EncodedPassword = "subscriptionPass";
+        config.subscriptionUpdate.trustRootCertUrl = "subscription.update.cert.com";
+        config.subscriptionUpdate.trustRootCertSha256Fingerprint = new byte[32];
+        Arrays.fill(config.subscriptionUpdate.trustRootCertSha256Fingerprint, (byte) 0x1f);
+
+        // Subscription parameters.
+        config.subscriptionCreationTimeInMs = format.parse("2016-02-01T10:00:00Z").getTime();
+        config.subscriptionExpirationTimeInMs = format.parse("2016-03-01T10:00:00Z").getTime();
+        config.subscriptionType = "Gold";
+        config.usageLimitDataLimit = 921890;
+        config.usageLimitStartTimeInMs = format.parse("2016-12-01T10:00:00Z").getTime();
+        config.usageLimitTimeLimitInMinutes = 120;
+        config.usageLimitUsageTimePeriodInMinutes = 99910;
 
         // HomeSP configuration.
         config.homeSp = new HomeSP();
@@ -97,7 +132,6 @@
         config.homeSp.otherHomePartners = new String[] {"other.fqdn.com"};
 
         // Credential configuration.
-        DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
         config.credential = new Credential();
         config.credential.creationTimeInMs = format.parse("2016-01-01T10:00:00Z").getTime();
         config.credential.expirationTimeInMs = format.parse("2016-02-01T10:00:00Z").getTime();
@@ -118,12 +152,46 @@
         config.credential.simCredential = new Credential.SimCredential();
         config.credential.simCredential.imsi = "imsi";
         config.credential.simCredential.eapType = 24;
+
+        // Policy configuration.
+        config.policy = new Policy();
+        config.policy.preferredRoamingPartnerList = new ArrayList<>();
+        Policy.RoamingPartner partner1 = new Policy.RoamingPartner();
+        partner1.fqdn = "test1.fqdn.com";
+        partner1.fqdnExactMatch = true;
+        partner1.priority = 127;
+        partner1.countries = "us,fr";
+        Policy.RoamingPartner partner2 = new Policy.RoamingPartner();
+        partner2.fqdn = "test2.fqdn.com";
+        partner2.fqdnExactMatch = false;
+        partner2.priority = 200;
+        partner2.countries = "*";
+        config.policy.preferredRoamingPartnerList.add(partner1);
+        config.policy.preferredRoamingPartnerList.add(partner2);
+        config.policy.minHomeDownlinkBandwidth = 23412;
+        config.policy.minHomeUplinkBandwidth = 9823;
+        config.policy.minRoamingDownlinkBandwidth = 9271;
+        config.policy.minRoamingUplinkBandwidth = 2315;
+        config.policy.excludedSsidList = new String[] {"excludeSSID"};
+        config.policy.requiredProtoPortMap = new HashMap<>();
+        config.policy.requiredProtoPortMap.put(12, "34,92,234");
+        config.policy.maximumBssLoadValue = 23;
+        config.policy.policyUpdate = new UpdateParameter();
+        config.policy.policyUpdate.updateIntervalInMinutes = 120;
+        config.policy.policyUpdate.updateMethod = UpdateParameter.UPDATE_METHOD_OMADM;
+        config.policy.policyUpdate.restriction = UpdateParameter.UPDATE_RESTRICTION_HOMESP;
+        config.policy.policyUpdate.serverUri = "policy.update.com";
+        config.policy.policyUpdate.username = "updateUser";
+        config.policy.policyUpdate.base64EncodedPassword = "updatePass";
+        config.policy.policyUpdate.trustRootCertUrl = "update.cert.com";
+        config.policy.policyUpdate.trustRootCertSha256Fingerprint = new byte[32];
+        Arrays.fill(config.policy.policyUpdate.trustRootCertSha256Fingerprint, (byte) 0x1f);
+
         return config;
     }
 
     /**
-     * Parse and verify all supported fields under PPS MO tree (currently only fields under
-     * HomeSP and Credential subtree).
+     * Parse and verify all supported fields under PPS MO tree.
      *
      * @throws Exception
      */
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/PolicyTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/PolicyTest.java
new file mode 100644
index 0000000..c371c49
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/PolicyTest.java
@@ -0,0 +1,304 @@
+/*
+ * 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.wifi.hotspot2.pps;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Base64;
+
+import org.junit.Test;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Unit tests for {@link android.net.wifi.hotspot2.pps.Policy}.
+ */
+@SmallTest
+public class PolicyTest {
+    private static final int MAX_NUMBER_OF_EXCLUDED_SSIDS = 128;
+    private static final int MAX_SSID_BYTES = 32;
+    private static final int MAX_PORT_STRING_BYTES = 64;
+
+    /**
+     * Helper function for creating a {@link Policy} for testing.
+     *
+     * @return {@link Policy}
+     */
+    private static Policy createPolicy() {
+        Policy policy = new Policy();
+        policy.minHomeDownlinkBandwidth = 123;
+        policy.minHomeUplinkBandwidth = 345;
+        policy.minRoamingDownlinkBandwidth = 567;
+        policy.minRoamingUplinkBandwidth = 789;
+        policy.excludedSsidList = new String[] {"ssid1", "ssid2"};
+        policy.requiredProtoPortMap = new HashMap<>();
+        policy.requiredProtoPortMap.put(12, "23,342,123");
+        policy.requiredProtoPortMap.put(23, "789,372,1235");
+        policy.maximumBssLoadValue = 12;
+
+        policy.preferredRoamingPartnerList = new ArrayList<>();
+        Policy.RoamingPartner partner1 = new Policy.RoamingPartner();
+        partner1.fqdn = "partner1.com";
+        partner1.fqdnExactMatch = true;
+        partner1.priority = 12;
+        partner1.countries = "us,jp";
+        Policy.RoamingPartner partner2 = new Policy.RoamingPartner();
+        partner2.fqdn = "partner2.com";
+        partner2.fqdnExactMatch = false;
+        partner2.priority = 42;
+        partner2.countries = "ca,fr";
+        policy.preferredRoamingPartnerList.add(partner1);
+        policy.preferredRoamingPartnerList.add(partner2);
+
+        policy.policyUpdate = new UpdateParameter();
+        policy.policyUpdate.updateIntervalInMinutes = 1712;
+        policy.policyUpdate.updateMethod = UpdateParameter.UPDATE_METHOD_OMADM;
+        policy.policyUpdate.restriction = UpdateParameter.UPDATE_RESTRICTION_HOMESP;
+        policy.policyUpdate.serverUri = "policy.update.com";
+        policy.policyUpdate.username = "username";
+        policy.policyUpdate.base64EncodedPassword =
+                Base64.encodeToString("password".getBytes(), Base64.DEFAULT);
+        policy.policyUpdate.trustRootCertUrl = "trust.cert.com";
+        policy.policyUpdate.trustRootCertSha256Fingerprint = new byte[32];
+
+        return policy;
+    }
+
+    /**
+     * Helper function for verifying Policy after parcel write then read.
+     * @param policyToWrite
+     * @throws Exception
+     */
+    private static void verifyParcel(Policy policyToWrite) throws Exception {
+        Parcel parcel = Parcel.obtain();
+        policyToWrite.writeToParcel(parcel, 0);
+
+        parcel.setDataPosition(0);    // Rewind data position back to the beginning for read.
+        Policy policyFromRead = Policy.CREATOR.createFromParcel(parcel);
+        assertTrue(policyFromRead.equals(policyToWrite));
+    }
+
+    /**
+     * Verify parcel read/write for an empty Policy.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void verifyParcelWithEmptyPolicy() throws Exception {
+        verifyParcel(new Policy());
+    }
+
+    /**
+     * Verify parcel read/write for a Policy with all fields set.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void verifyParcelWithFullPolicy() throws Exception {
+        verifyParcel(createPolicy());
+    }
+
+    /**
+     * Verify parcel read/write for a Policy without protocol port map.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void verifyParcelWithoutProtoPortMap() throws Exception {
+        Policy policy = createPolicy();
+        policy.requiredProtoPortMap = null;
+        verifyParcel(policy);
+    }
+
+    /**
+     * Verify parcel read/write for a Policy without preferred roaming partner list.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void verifyParcelWithoutPreferredRoamingPartnerList() throws Exception {
+        Policy policy = createPolicy();
+        policy.preferredRoamingPartnerList = null;
+        verifyParcel(policy);
+    }
+
+    /**
+     * Verify parcel read/write for a Policy without policy update parameters.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void verifyParcelWithoutPolicyUpdate() throws Exception {
+        Policy policy = createPolicy();
+        policy.policyUpdate = null;
+        verifyParcel(policy);
+    }
+
+    /**
+     * Verify that policy created using copy constructor with null source should be the same
+     * as the policy created using default constructor.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void verifyCopyConstructionWithNullSource() throws Exception {
+        Policy copyPolicy = new Policy(null);
+        Policy defaultPolicy = new Policy();
+        assertTrue(defaultPolicy.equals(copyPolicy));
+    }
+
+    /**
+     * Verify that policy created using copy constructor with a valid source should be the
+     * same as the source.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void verifyCopyConstructionWithFullPolicy() throws Exception {
+        Policy policy = createPolicy();
+        Policy copyPolicy = new Policy(policy);
+        assertTrue(policy.equals(copyPolicy));
+    }
+
+    /**
+     * Verify that a default policy (with no informatio) is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validatePolicyWithDefault() throws Exception {
+        Policy policy = new Policy();
+        assertFalse(policy.validate());
+    }
+
+    /**
+     * Verify that a policy created using {@link #createPolicy} is valid, since all fields are
+     * filled in with valid values.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validatePolicyWithFullPolicy() throws Exception {
+        assertTrue(createPolicy().validate());
+    }
+
+    /**
+     * Verify that a policy without policy update parameters is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validatePolicyWithoutPolicyUpdate() throws Exception {
+        Policy policy = createPolicy();
+        policy.policyUpdate = null;
+        assertFalse(policy.validate());
+    }
+
+    /**
+     * Verify that a policy with invalid policy update parameters is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validatePolicyWithInvalidPolicyUpdate() throws Exception {
+        Policy policy = createPolicy();
+        policy.policyUpdate = new UpdateParameter();
+        assertFalse(policy.validate());
+    }
+
+    /**
+     * Verify that a policy with a preferred roaming partner with FQDN not specified is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validatePolicyWithRoamingPartnerWithoutFQDN() throws Exception {
+        Policy policy = createPolicy();
+        Policy.RoamingPartner partner = new Policy.RoamingPartner();
+        partner.fqdnExactMatch = true;
+        partner.priority = 12;
+        partner.countries = "us,jp";
+        policy.preferredRoamingPartnerList.add(partner);
+        assertFalse(policy.validate());
+    }
+
+    /**
+     * Verify that a policy with a preferred roaming partner with countries not specified is
+     * invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validatePolicyWithRoamingPartnerWithoutCountries() throws Exception {
+        Policy policy = createPolicy();
+        Policy.RoamingPartner partner = new Policy.RoamingPartner();
+        partner.fqdn = "test.com";
+        partner.fqdnExactMatch = true;
+        partner.priority = 12;
+        policy.preferredRoamingPartnerList.add(partner);
+        assertFalse(policy.validate());
+    }
+
+    /**
+     * Verify that a policy with a proto-port tuple that contains an invalid port string is
+     * invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validatePolicyWithInvalidPortStringInProtoPortMap() throws Exception {
+        Policy policy = createPolicy();
+        byte[] rawPortBytes = new byte[MAX_PORT_STRING_BYTES + 1];
+        policy.requiredProtoPortMap.put(324, new String(rawPortBytes, StandardCharsets.UTF_8));
+        assertFalse(policy.validate());
+    }
+
+    /**
+     * Verify that a policy with number of excluded SSIDs exceeded the max is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validatePolicyWithSsidExclusionListSizeExceededMax() throws Exception {
+        Policy policy = createPolicy();
+        policy.excludedSsidList = new String[MAX_NUMBER_OF_EXCLUDED_SSIDS + 1];
+        Arrays.fill(policy.excludedSsidList, "ssid");
+        assertFalse(policy.validate());
+    }
+
+    /**
+     * Verify that a policy with an invalid SSID in the excluded SSID list is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validatePolicyWithInvalidSsid() throws Exception {
+        Policy policy = createPolicy();
+        byte[] rawSsidBytes = new byte[MAX_SSID_BYTES + 1];
+        Arrays.fill(rawSsidBytes, (byte) 'a');
+        policy.excludedSsidList = new String[] {new String(rawSsidBytes, StandardCharsets.UTF_8)};
+        assertFalse(policy.validate());
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/UpdateParameterTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/UpdateParameterTest.java
new file mode 100644
index 0000000..6bf0db1b
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/UpdateParameterTest.java
@@ -0,0 +1,348 @@
+/*
+ * 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.wifi.hotspot2.pps;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Base64;
+
+import org.junit.Test;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Unit tests for {@link android.net.wifi.hotspot2.pps.UpdateParameter}.
+ */
+@SmallTest
+public class UpdateParameterTest {
+    private static final int MAX_URI_BYTES = 1023;
+    private static final int MAX_URL_BYTES = 1023;
+    private static final int MAX_USERNAME_BYTES = 63;
+    private static final int MAX_PASSWORD_BYTES = 255;
+    private static final int CERTIFICATE_SHA256_BYTES = 32;
+
+    /**
+     * Helper function for creating a {@link UpdateParameter} for testing.
+     *
+     * @return {@link UpdateParameter}
+     */
+    private static UpdateParameter createUpdateParameter() {
+        UpdateParameter updateParam = new UpdateParameter();
+        updateParam.updateIntervalInMinutes = 1712;
+        updateParam.updateMethod = UpdateParameter.UPDATE_METHOD_OMADM;
+        updateParam.restriction = UpdateParameter.UPDATE_RESTRICTION_HOMESP;
+        updateParam.serverUri = "server.pdate.com";
+        updateParam.username = "username";
+        updateParam.base64EncodedPassword =
+                Base64.encodeToString("password".getBytes(), Base64.DEFAULT);
+        updateParam.trustRootCertUrl = "trust.cert.com";
+        updateParam.trustRootCertSha256Fingerprint = new byte[32];
+        return updateParam;
+    }
+
+    /**
+     * Helper function for verifying UpdateParameter after parcel write then read.
+     * @param paramToWrite The UpdateParamter to verify
+     * @throws Exception
+     */
+    private static void verifyParcel(UpdateParameter paramToWrite) throws Exception {
+        Parcel parcel = Parcel.obtain();
+        paramToWrite.writeToParcel(parcel, 0);
+
+        parcel.setDataPosition(0);    // Rewind data position back to the beginning for read.
+        UpdateParameter paramFromRead = UpdateParameter.CREATOR.createFromParcel(parcel);
+        assertTrue(paramFromRead.equals(paramToWrite));
+    }
+
+    /**
+     * Verify parcel read/write for an empty UpdateParameter.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void verifyParcelWithEmptyUpdateParameter() throws Exception {
+        verifyParcel(new UpdateParameter());
+    }
+
+    /**
+     * Verify parcel read/write for a UpdateParameter with all fields set.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void verifyParcelWithFullUpdateParameter() throws Exception {
+        verifyParcel(createUpdateParameter());
+    }
+
+    /**
+     * Verify that UpdateParameter created using copy constructor with null source should be the
+     * same as the UpdateParameter created using default constructor.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void verifyCopyConstructionWithNullSource() throws Exception {
+        UpdateParameter copyParam = new UpdateParameter(null);
+        UpdateParameter defaultParam = new UpdateParameter();
+        assertTrue(defaultParam.equals(copyParam));
+    }
+
+    /**
+     * Verify that UpdateParameter created using copy constructor with a valid source should be the
+     * same as the source.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void verifyCopyConstructionWithFullUpdateParameter() throws Exception {
+        UpdateParameter origParam = createUpdateParameter();
+        UpdateParameter copyParam = new UpdateParameter(origParam);
+        assertTrue(origParam.equals(copyParam));
+    }
+
+    /**
+     * Verify that a default UpdateParameter is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateUpdateParameterWithDefault() throws Exception {
+        UpdateParameter updateParam = new UpdateParameter();
+        assertFalse(updateParam.validate());
+    }
+
+    /**
+     * Verify that an UpdateParameter created using {@link #createUpdateParameter} is valid,
+     * since all fields are filled in with valid values.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateUpdateParameterWithFullPolicy() throws Exception {
+        assertTrue(createUpdateParameter().validate());
+    }
+
+    /**
+     * Verify that an UpdateParameter with an unknown update method is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateUpdateParameterWithUnknowMethod() throws Exception {
+        UpdateParameter updateParam = createUpdateParameter();
+        updateParam.updateMethod = "adsfasd";
+        assertFalse(updateParam.validate());
+    }
+
+    /**
+     * Verify that an UpdateParameter with an unknown restriction is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateUpdateParameterWithUnknowRestriction() throws Exception {
+        UpdateParameter updateParam = createUpdateParameter();
+        updateParam.restriction = "adsfasd";
+        assertFalse(updateParam.validate());
+    }
+
+    /**
+     * Verify that an UpdateParameter with an username exceeding maximum size is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateUpdateParameterWithUsernameExceedingMaxSize() throws Exception {
+        UpdateParameter updateParam = createUpdateParameter();
+        byte[] rawUsernameBytes = new byte[MAX_USERNAME_BYTES + 1];
+        Arrays.fill(rawUsernameBytes, (byte) 'a');
+        updateParam.username = new String(rawUsernameBytes, StandardCharsets.UTF_8);
+        assertFalse(updateParam.validate());
+    }
+
+    /**
+     * Verify that an UpdateParameter with an empty username is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateUpdateParameterWithEmptyUsername() throws Exception {
+        UpdateParameter updateParam = createUpdateParameter();
+        updateParam.username = null;
+        assertFalse(updateParam.validate());
+    }
+
+    /**
+     * Verify that an UpdateParameter with a password exceeding maximum size is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateUpdateParameterWithPasswordExceedingMaxSize() throws Exception {
+        UpdateParameter updateParam = createUpdateParameter();
+        byte[] rawPasswordBytes = new byte[MAX_PASSWORD_BYTES + 1];
+        Arrays.fill(rawPasswordBytes, (byte) 'a');
+        updateParam.base64EncodedPassword = new String(rawPasswordBytes, StandardCharsets.UTF_8);
+        assertFalse(updateParam.validate());
+    }
+
+    /**
+     * Verify that an UpdateParameter with an empty password is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateUpdateParameterWithEmptyPassword() throws Exception {
+        UpdateParameter updateParam = createUpdateParameter();
+        updateParam.base64EncodedPassword = null;
+        assertFalse(updateParam.validate());
+    }
+
+    /**
+     * Verify that an UpdateParameter with a Base64 encoded password that contained invalid padding
+     * is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateUpdateParameterWithPasswordContainedInvalidPadding() throws Exception {
+        UpdateParameter updateParam = createUpdateParameter();
+        updateParam.base64EncodedPassword = updateParam.base64EncodedPassword + "=";
+        assertFalse(updateParam.validate());
+    }
+
+    /**
+     * Verify that an UpdateParameter without trust root certificate URL is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateUpdateParameterWithoutTrustRootCertUrl() throws Exception {
+        UpdateParameter updateParam = createUpdateParameter();
+        updateParam.trustRootCertUrl = null;
+        assertFalse(updateParam.validate());
+    }
+
+    /**
+     * Verify that an UpdateParameter with invalid trust root certificate URL is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateUpdateParameterWithInvalidTrustRootCertUrl() throws Exception {
+        UpdateParameter updateParam = createUpdateParameter();
+        byte[] rawUrlBytes = new byte[MAX_URL_BYTES + 1];
+        Arrays.fill(rawUrlBytes, (byte) 'a');
+        updateParam.trustRootCertUrl = new String(rawUrlBytes, StandardCharsets.UTF_8);
+        assertFalse(updateParam.validate());
+    }
+
+    /**
+     * Verify that an UpdateParameter without trust root certificate SHA-256 fingerprint is
+     * invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateUpdateParameterWithouttrustRootCertSha256Fingerprint() throws Exception {
+        UpdateParameter updateParam = createUpdateParameter();
+        updateParam.trustRootCertSha256Fingerprint = null;
+        assertFalse(updateParam.validate());
+    }
+
+    /**
+     * Verify that an UpdateParameter with an incorrect size trust root certificate SHA-256
+     * fingerprint is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateUpdateParameterWithInvalidtrustRootCertSha256Fingerprint() throws Exception {
+        UpdateParameter updateParam = createUpdateParameter();
+        updateParam.trustRootCertSha256Fingerprint = new byte[CERTIFICATE_SHA256_BYTES + 1];
+        assertFalse(updateParam.validate());
+
+        updateParam.trustRootCertSha256Fingerprint = new byte[CERTIFICATE_SHA256_BYTES - 1];
+        assertFalse(updateParam.validate());
+    }
+
+    /**
+     * Verify that an UpdateParameter without server URI is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateUpdateParameterWithoutServerUri() throws Exception {
+        UpdateParameter updateParam = createUpdateParameter();
+        updateParam.serverUri = null;
+        assertFalse(updateParam.validate());
+    }
+
+    /**
+     * Verify that an UpdateParameter with an invalid server URI is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validatePolicyWithInvalidServerUri() throws Exception {
+        UpdateParameter updateParam = createUpdateParameter();
+        byte[] rawUriBytes = new byte[MAX_URI_BYTES + 1];
+        Arrays.fill(rawUriBytes, (byte) 'a');
+        updateParam.serverUri = new String(rawUriBytes, StandardCharsets.UTF_8);
+        assertFalse(updateParam.validate());
+    }
+
+    /**
+     * Verify that an UpdateParameter with update interval set to "never" will not perform
+     * validation on other parameters, since update is not applicable in this case.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateUpdateParameterWithNoServerCheck() throws Exception {
+        UpdateParameter updateParam = new UpdateParameter();
+        updateParam.updateIntervalInMinutes = UpdateParameter.UPDATE_CHECK_INTERVAL_NEVER;
+        updateParam.username = null;
+        updateParam.base64EncodedPassword = null;
+        updateParam.updateMethod = null;
+        updateParam.restriction = null;
+        updateParam.serverUri = null;
+        updateParam.trustRootCertUrl = null;
+        updateParam.trustRootCertSha256Fingerprint = null;
+        assertTrue(updateParam.validate());
+    }
+
+    /**
+     * Verify that an UpdateParameter with unset update interval is invalid.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void validateUpdateParameterWithoutUpdateInterval() throws Exception {
+        UpdateParameter updateParam = createUpdateParameter();
+        updateParam.updateIntervalInMinutes = Long.MIN_VALUE;
+        assertFalse(updateParam.validate());
+    }
+}